Skip to content

Commit

Permalink
Merge pull request #1383 from janezd/pca-mark
Browse files Browse the repository at this point in the history
[ENH] PCA: Add lines and labels showing the explained variance
  • Loading branch information
thocevar authored Jul 1, 2016
2 parents e24aa39 + 06a3a7b commit ae50e78
Showing 1 changed file with 33 additions and 11 deletions.
44 changes: 33 additions & 11 deletions Orange/widgets/unsupervised/owpca.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from Orange.preprocess import Normalize
from Orange.projection import PCA
from Orange.widgets import widget, gui, settings
from Orange.widgets.io import FileFormat

try:
from orangecontrib import remote
Expand Down Expand Up @@ -125,6 +124,8 @@ def __init__(self):
axis.setLabel("Principal Components")
axis = self.plot.getAxis("left")
axis.setLabel("Proportion of variance")
self.plot_horlabels = []
self.plot_horlines = []

self.plot.getViewBox().setMenuEnabled(False)
self.plot.getViewBox().setMouseEnabled(False, False)
Expand Down Expand Up @@ -199,6 +200,8 @@ def clear(self):
self._variance_ratio = None
self._cumulative = None
self._line = None
self.plot_horlabels = []
self.plot_horlines = []
self.plot.clear()

def get_model(self):
Expand Down Expand Up @@ -231,29 +234,49 @@ def _setup_plot(self):
antialias=True,
name="Cumulative Variance")

cutpos = self._nselected_components() - 1
self._line = pg.InfiniteLine(
angle=90, pos=self._nselected_components() - 1, movable=True,
bounds=(0, p - 1)
)
angle=90, pos=cutpos, movable=True, bounds=(0, p - 1))
self._line.setCursor(Qt.SizeHorCursor)
self._line.setPen(pg.mkPen(QColor(Qt.darkGray), width=5))
self._line.setPen(pg.mkPen(QColor(Qt.black), width=2))
self._line.sigPositionChanged.connect(self._on_cut_changed)

self.plot.addItem(self._line)

self.plot_horlines = (
pg.PlotCurveItem(pen=pg.mkPen(QColor(Qt.blue), style=Qt.DashLine)),
pg.PlotCurveItem(pen=pg.mkPen(QColor(Qt.blue), style=Qt.DashLine)))
self.plot_horlabels = (
pg.TextItem(color=QColor(Qt.black), anchor=(1, 0)),
pg.TextItem(color=QColor(Qt.black), anchor=(1, 1)))
for item in self.plot_horlabels + self.plot_horlines:
self.plot.addItem(item)
self._set_horline_pos()

self.plot.setRange(xRange=(0.0, p - 1), yRange=(0.0, 1.0))
self._update_axis()

def _set_horline_pos(self):
cutidx = self.ncomponents - 1
for line, label, curve in zip(self.plot_horlines, self.plot_horlabels,
(self._variance_ratio, self._cumulative)):
y = curve[cutidx]
line.setData([-1, cutidx], 2 * [y])
label.setPos(cutidx, y)
label.setPlainText("{:.2f}".format(y))

def _on_cut_changed(self, line):
# cut changed by means of a cut line over the scree plot.
value = line.value()
self._line.setValue(round(value))
value = int(round(line.value()))
self._line.setValue(value)
current = self._nselected_components()
components = int(numpy.floor(value)) + 1
components = value + 1

if not (self.ncomponents == 0 and
components == len(self._variance_ratio)):
self.ncomponents = components

self._set_horline_pos()

if self._pca is not None:
self.variance_covered = self._cumulative[components - 1] * 100

Expand Down Expand Up @@ -384,5 +407,4 @@ def main():
return rval

if __name__ == "__main__":
import sys
sys.exit(main())
main()

0 comments on commit ae50e78

Please sign in to comment.