Skip to content

Commit a2afed5

Browse files
committed
PCA: Show covered variance in output tables
1 parent f9d78d6 commit a2afed5

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

Orange/widgets/unsupervised/owpca.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -293,22 +293,36 @@ def commit(self):
293293
self._transformed = self._pca(self.data)
294294
transformed = self._transformed
295295

296+
if self._variance_ratio is not None:
297+
for var, explvar in zip(
298+
transformed.domain.attributes,
299+
self._variance_ratio[:self.ncomponents]):
300+
var.attributes["variance"] = round(explvar, 6)
296301
domain = Domain(
297302
transformed.domain.attributes[:self.ncomponents],
298303
self.data.domain.class_vars,
299304
self.data.domain.metas
300305
)
301306
transformed = transformed.from_table(domain, transformed)
307+
302308
# prevent caching new features by defining compute_value
303309
proposed = [a.name for a in self._pca.orig_domain.attributes]
304310
meta_name = get_unique_names(proposed, 'components')
305-
dom = Domain(
306-
[ContinuousVariable(name, compute_value=lambda _: None)
307-
for name in proposed],
308-
metas=[StringVariable(name=meta_name)])
311+
meta_vars = [StringVariable(name=meta_name)]
309312
metas = numpy.array([['PC{}'.format(i + 1)
310313
for i in range(self.ncomponents)]],
311314
dtype=object).T
315+
if self._variance_ratio is not None:
316+
variance_name = get_unique_names(proposed, "variance")
317+
meta_vars.append(ContinuousVariable(variance_name))
318+
metas = numpy.hstack(
319+
(metas,
320+
self._variance_ratio[:self.ncomponents, None]))
321+
322+
dom = Domain(
323+
[ContinuousVariable(name, compute_value=lambda _: None)
324+
for name in proposed],
325+
metas=meta_vars)
312326
components = Table(dom, self._pca.components_[:self.ncomponents],
313327
metas=metas)
314328
components.name = 'components'

Orange/widgets/unsupervised/tests/test_owpca.py

+21
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,27 @@ def test_unique_domain_components(self):
9595
out = self.get_output(self.widget.Outputs.components)
9696
self.assertEqual(out.domain.metas[0].name, 'components (1)')
9797

98+
def test_variance_attr(self):
99+
self.widget.ncomponents = 2
100+
self.send_signal(self.widget.Inputs.data, self.iris)
101+
self.wait_until_stop_blocking()
102+
self.widget._variance_ratio = np.array([0.5, 0.25, 0.2, 0.05])
103+
self.widget.unconditional_commit()
104+
105+
result = self.get_output(self.widget.Outputs.transformed_data)
106+
pc1, pc2 = result.domain.attributes
107+
self.assertEqual(pc1.attributes["variance"], 0.5)
108+
self.assertEqual(pc2.attributes["variance"], 0.25)
109+
110+
result = self.get_output(self.widget.Outputs.data)
111+
pc1, pc2 = result.domain.metas
112+
self.assertEqual(pc1.attributes["variance"], 0.5)
113+
self.assertEqual(pc2.attributes["variance"], 0.25)
114+
115+
result = self.get_output(self.widget.Outputs.components)
116+
np.testing.assert_almost_equal(result.get_column_view("variance")[0].T,
117+
[0.5, 0.25])
118+
98119
def test_sparse_data(self):
99120
"""Check that PCA returns the same results for both dense and sparse data."""
100121
dense_data, sparse_data = self.iris, self.iris.to_sparse()

0 commit comments

Comments
 (0)