Skip to content

Commit

Permalink
Output to OWCorrespondence
Browse files Browse the repository at this point in the history
  • Loading branch information
PrimozGodec committed Nov 11, 2019
1 parent 05c8ae0 commit 32b66f1
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 5 deletions.
34 changes: 30 additions & 4 deletions Orange/widgets/unsupervised/owcorrespondence.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,16 @@

import pyqtgraph as pg
import Orange.data
from Orange.data import Table, Domain, ContinuousVariable, StringVariable
from Orange.statistics import contingency

from Orange.widgets import widget, gui, settings
from Orange.widgets.utils import itemmodels, colorpalette
from Orange.widgets.utils.widgetpreview import WidgetPreview

from Orange.widgets.visualize.owscatterplotgraph import ScatterPlotItem
from Orange.widgets.widget import Input
from Orange.widgets.widget import Input, Output
from orangewidget.settings import Setting


class ScatterPlotItem(pg.ScatterPlotItem):
Expand Down Expand Up @@ -51,11 +53,15 @@ class OWCorrespondenceAnalysis(widget.OWWidget):
class Inputs:
data = Input("Data", Orange.data.Table)

class Outputs:
coordinates = Output("Coordinates", Orange.data.Table)

Invalidate = QEvent.registerEventType()

settingsHandler = settings.DomainContextHandler()

selected_var_indices = settings.ContextSetting([])
auto_commit = Setting(True)

graph_name = "plot.plotItem"

Expand Down Expand Up @@ -96,6 +102,8 @@ def __init__(self):
gui.vBox(self.controlArea, "Contribution to Inertia"), "\n"
)

gui.auto_send(self.controlArea, self, "auto_commit")

gui.rubber(self.controlArea)

self.plot = pg.PlotWidget(background="w")
Expand Down Expand Up @@ -127,6 +135,24 @@ def set_data(self, data):
self._restore_selection()
self._update_CA()

def commit(self):
output_table = None
if self.ca is not None:
sel_vars = self.selected_vars()
if len(sel_vars) == 2:
rf = np.vstack((self.ca.row_factors, self.ca.col_factors))
else:
rf = self.ca.row_factors
vars = [(val.name, var) for val in sel_vars for var in val.values]
output_table = Table(
Domain([ContinuousVariable(f"Component {i + 1}")
for i in range(rf.shape[1])],
metas=[StringVariable("Variable"),
StringVariable("Value")]),
rf, metas=vars
)
self.Outputs.coordinates.send(output_table)

def clear(self):
self.data = None
self.ca = None
Expand All @@ -145,8 +171,7 @@ def restore(view, indices):
restore(self.varview, self.selected_var_indices)

def _p_axes(self):
# return (0, 1)
return (self.component_x, self.component_y)
return self.component_x, self.component_y

def _var_changed(self):
self.selected_var_indices = sorted(
Expand Down Expand Up @@ -182,6 +207,7 @@ def _update_CA(self):

self._setup_plot()
self._update_info()
self.commit()

def update_XY(self):
self.axis_x_cb.clear()
Expand Down Expand Up @@ -406,4 +432,4 @@ def inertia_of_axis(self):


if __name__ == "__main__": # pragma: no cover
WidgetPreview(OWCorrespondenceAnalysis).run(Orange.data.Table("smokers_ct"))
WidgetPreview(OWCorrespondenceAnalysis).run(Orange.data.Table("titanic"))
18 changes: 17 additions & 1 deletion Orange/widgets/unsupervised/tests/test_owcorrespondence.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
from Orange.data import Table, Domain, DiscreteVariable, ContinuousVariable
from Orange.widgets.tests.base import WidgetTest
from Orange.widgets.unsupervised.owcorrespondence \
import OWCorrespondenceAnalysis
import OWCorrespondenceAnalysis, select_rows
from Orange.widgets.utils import itemmodels


class TestOWCorrespondence(WidgetTest):
def setUp(self):
self.widget = self.create_widget(OWCorrespondenceAnalysis)
self.data = Table("titanic")

def test_no_data(self):
"""Check that the widget doesn't crash on empty data"""
Expand Down Expand Up @@ -73,3 +75,17 @@ def test_no_discrete_variables(self):
self.assertTrue(self.widget.Error.no_disc_vars.is_shown())
self.send_signal(self.widget.Inputs.data, Table("iris"))
self.assertFalse(self.widget.Error.no_disc_vars.is_shown())

def test_outputs(self):
w = self.widget

self.assertIsNone(self.get_output(w.Outputs.coordinates), None)
self.send_signal(self.widget.Inputs.data, self.data)
self.assertTupleEqual(self.get_output(w.Outputs.coordinates).X.shape,
(6, 2))
select_rows(w.varview, [0, 1, 2])
w.commit()
self.assertTupleEqual(self.get_output(w.Outputs.coordinates).X.shape,
(8, 8))
self.send_signal(self.widget.Inputs.data, None)
self.assertIsNone(self.get_output(w.Outputs.coordinates), None)
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Correspondence analysis for categorical multivariate data.

- Data: input dataset

**Outputs**

- Coordinates: coordinates of all components

[Correspondence Analysis](https://en.wikipedia.org/wiki/Correspondence_analysis) (CA) computes the CA linear transformation of the input data. While it is similar to PCA, CA computes linear transformation on discrete rather than on continuous data.

![](images/CorrespondenceAnalysis-stamped.png)
Expand Down

0 comments on commit 32b66f1

Please sign in to comment.