From b7d8703e4f1a0e95f327a307de2e8a1edc50f651 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 25 Mar 2022 11:38:02 +0100 Subject: [PATCH 1/9] OWDiscretize: Reduce interface, add nicer binnings --- Orange/preprocess/discretize.py | 182 ++- Orange/preprocess/tests/test_discretize.py | 319 ++++- Orange/widgets/data/owdiscretize.py | 1267 +++++++++-------- .../widgets/data/tests/test_owdiscretize.py | 237 ++- 4 files changed, 1308 insertions(+), 697 deletions(-) diff --git a/Orange/preprocess/discretize.py b/Orange/preprocess/discretize.py index ba84b1ec424..3c50fbb4d7c 100644 --- a/Orange/preprocess/discretize.py +++ b/Orange/preprocess/discretize.py @@ -8,7 +8,7 @@ import numpy as np import scipy.sparse as sp -from Orange.data import DiscreteVariable, Domain +from Orange.data import DiscreteVariable, Domain, TimeVariable from Orange.data.sql.table import SqlTable from Orange.statistics import distribution, contingency, util as ut from Orange.statistics.basic_stats import BasicStats @@ -58,13 +58,17 @@ def _fmt_interval(low, high, formatter): return f"{formatter(low)} - {formatter(high)}" @classmethod - def create_discretized_var(cls, var, points): - def fmt(val): - sval = var.str_val(val) - # For decimal numbers, remove trailing 0's and . if no decimals left - if re.match(r"^\d+\.\d+", sval): - return sval.rstrip("0").rstrip(".") - return sval + def create_discretized_var(cls, var, points, ndigits=None): + if ndigits is None: + def fmt(val): + sval = var.str_val(val) + # For decimal numbers, remove trailing 0's and . if no decimals left + if re.match(r"^\d+\.\d+", sval): + return sval.rstrip("0").rstrip(".") + return sval + else: + def fmt(val): + return f"{val:.{ndigits}f}" lpoints = list(points) if lpoints: @@ -186,7 +190,149 @@ def _split_eq_width(self, min, max): if np.isnan(min) or np.isnan(max) or min == max: return [] dif = (max - min) / self.n - return [min + (i + 1) * dif for i in range(self.n - 1)] + return [min + i * dif for i in range(1, self.n)] + + +class TooManyIntervals(ValueError): + pass + + +class FixedWidth(Discretization): + def __init__(self, width, digits=None): + super().__init__() + self.width = width + self.digits = digits + + def __call__(self, data, attribute): + values = data[:, attribute] + values = values.X if values.X.size else values.Y + points = [] + if values.size: + min, max = ut.nanmin(values), ut.nanmax(values) + if not np.isnan(min): + minf = int(1 + np.floor(min / self.width)) + maxf = int(1 + np.floor(max / self.width)) + if maxf - minf - 1 >= 100: + raise TooManyIntervals + points = [i * self.width for i in range(minf, maxf)] + return Discretizer.create_discretized_var( + data.domain[attribute], points, ndigits=self.digits) + + +class FixedTimeWidth(Discretization): + def __init__(self, width, unit): + # unit: 0=year, 1=month, 2=day, 3=hour, 4=minute, 5=second + # for week, use day with a width of 7 + super().__init__() + self.width = width + self.unit = unit + + def __call__(self, data, attribute): + fmt = ["%Y", "%y %b", "%y %b %d", "%y %b %d %H:%M", "%y %b %d %H:%M", + "%H:%M:%S"][self.unit] + values = data[:, attribute] + values = values.X if values.X.size else values.Y + times = [] + if values.size: + mn, mx = ut.nanmin(values), ut.nanmax(values) + if not np.isnan(mn): + mn = utc_from_timestamp(mn).timetuple() + mx = utc_from_timestamp(mx).timetuple() + times = _time_range(mn, mx, self.unit, self.width, 0, 100) + if times is None: + raise TooManyIntervals + times = [time.struct_time(t + (0, 0, 0)) for t in times][1:-1] + points = np.array([calendar.timegm(t) for t in times]) + values = [time.strftime(fmt, t) for t in times] + values = _simplified_time_intervals(values) + var = data.domain[attribute] + return DiscreteVariable(name=var.name, values=values, + compute_value=Discretizer(var, points), + sparse=var.sparse) + + +def _simplified_time_intervals(labels): + def no_common(a, b): + for i, pa, pb in zip(count(), a, b): + if pa != pb: + if common + i == 2: + i -= 1 + return b[i:] + + + if not labels: + return [] + common = 100 + labels = [label.split() for label in labels] + for common, parts in enumerate(map(set, zip(*labels))): + if len(parts) > 1: + break + if common == 2: # If we keep days, we must also keep months + common = 1 + labels = [label[common:] for label in labels] + join = " ".join + return [f"< {join(labels[0])}"] + [ + f"{join(low)} - {join(no_common(low, high))}" + for low, high in zip(labels, labels[1:]) + ] + [f"≥ {join(labels[-1])}"] + + + +class Binning(Discretization): + """Discretization with nice thresholds + + This class creates different decimal or time binnings and picks the one + in which the number of interval is closest to the desired number. + The difference is measured as proportion; e.g. having 30 % less intervals + is the same difference as having 30 % too many. + + .. attribute:: n + + Desired number of bins (default: 4). + """ + def __init__(self, n=4): + self.n = n + + def __call__(self, data, attribute): + attribute = data.domain[attribute] + values = data[:, attribute] + values = values.X if values.X.size else values.Y + if not values.size: + return self._create_binned_var(None, attribute) + + var = data.domain[attribute] + if isinstance(var, TimeVariable): + binnings = time_binnings(values) + else: + binnings = decimal_binnings(values) + return self._create_binned_var(binnings, attribute) + + def _create_binned_var(self, binnings, variable): + if not binnings: + return Discretizer.create_discretized_var(variable, []) + + # If self.n is 2, require two intervals (one threshold, excluding top + # and bottom), else require at least three intervals + # ... unless this is the only option, in which case we use it + # Break ties in favour of more bins + binning = min( + (binning for binning in binnings + if len(binning.thresholds) - 2 >= 1 + (self.n != 2)), + key=lambda binning: (abs(self.n - (len(binning.short_labels) - 1)), + -len(binning.short_labels)), + default=binnings[-1]) + + blabels = binning.labels[1:-1] + labels = [f"< {blabels[0]}"] + [ + f"{lab1} - {lab2}" for lab1, lab2 in zip(blabels, blabels[1:]) + ] + [f"≥ {blabels[-1]}"] + + discretizer = Discretizer(variable, list(binning.thresholds[1:-1])) + dvar = DiscreteVariable(name=variable.name, values=labels, + compute_value=discretizer, + sparse=variable.sparse) + dvar.source_variable = variable + return dvar class BinDefinition(NamedTuple): @@ -234,7 +380,7 @@ def decimal_binnings( data, *, min_width=0, min_bins=2, max_bins=50, min_unique=5, add_unique=0, factors=(0.01, 0.02, 0.025, 0.05, 0.1, 0.2, 0.25, 0.5, 1, 2, 5, 10, 20), - label_fmt="%g"): + label_fmt="%g") -> List[BinDefinition]: """ Find a set of nice splits of data into bins @@ -283,13 +429,6 @@ def decimal_binnings( or a function for formatting thresholds (e.g. var.str_val) Returns: - bin_boundaries (list of np.ndarray): a list of bin boundaries, - including the top boundary of the last interval, hence the list - size equals the number bins + 1. These array match the `bin` - argument of `numpy.histogram`. - - This is returned if `return_defs` is left `True`. - bin_definition (list of BinDefinition): `BinDefinition` is a named tuple containing the beginning of the first bin (`start`), number of bins (`nbins`) and their widths @@ -297,8 +436,6 @@ def decimal_binnings( elements, which describes bins of unequal width and is used for binnings that match the unique values in the data (see `min_unique` and `add_unique`). - - This is returned if `return_defs` is `False`. """ bins = [] @@ -329,7 +466,8 @@ def decimal_binnings( return bins -def time_binnings(data, *, min_bins=2, max_bins=50, min_unique=5, add_unique=0): +def time_binnings(data, *, min_bins=2, max_bins=50, min_unique=5, add_unique=0 + ) -> List[BinDefinition]: """ Find a set of nice splits of time variable data into bins @@ -355,7 +493,7 @@ def time_binnings(data, *, min_bins=2, max_bins=50, min_unique=5, add_unique=0): number of unique values Returns: - bin_boundaries (list): a list of possible binning. + bin_boundaries (list of BinDefinition): a list of possible binning. Each element of `bin_boundaries` is a tuple consisting of a label describing the bin size (e.g. `2 weeks`) and a list of thresholds. Thresholds are given as pairs @@ -448,7 +586,7 @@ def _simplified_labels(labels): to_remove = "42" while True: firsts = {f for f, *_ in (lab.split() for lab in labels)} - if len(firsts) > 1: + if len(firsts) != 1: # can be 0 if there are no labels break to_remove = firsts.pop() flen = len(to_remove) diff --git a/Orange/preprocess/tests/test_discretize.py b/Orange/preprocess/tests/test_discretize.py index e292d66242f..6d5d07e2d4b 100644 --- a/Orange/preprocess/tests/test_discretize.py +++ b/Orange/preprocess/tests/test_discretize.py @@ -2,13 +2,328 @@ # pylint: disable=line-too-long import calendar import unittest +from unittest.mock import patch, Mock from time import struct_time, mktime import numpy as np -from Orange.data import ContinuousVariable +from Orange.data import ContinuousVariable, TimeVariable, Table, Domain from Orange.preprocess.discretize import \ - _time_binnings, time_binnings, BinDefinition, Discretizer + _time_binnings, time_binnings, BinDefinition, Discretizer, FixedWidth, \ + FixedTimeWidth , Binning, \ + TooManyIntervals + + +class TestFixedWidth(unittest.TestCase): + def test_discretization(self): + x = np.array([[0.21, 0.335, 0, 0.26, np.nan], + [0] * 5, + [np.nan] * 5]).T + domain = Domain([ContinuousVariable(f"c{i}") for i in range(x.shape[1])]) + data = Table.from_numpy(domain, x, None) + + dvar = FixedWidth(0.1, 2)(data, 0) + np.testing.assert_almost_equal(dvar.compute_value.points, + (0.1, 0.2, 0.3)) + self.assertEqual(dvar.values, + ('< 0.10', '0.10 - 0.20', '0.20 - 0.30', '≥ 0.30')) + + dvar = FixedWidth(0.2, 1)(data, 0) + np.testing.assert_almost_equal(dvar.compute_value.points, (0.2, )) + self.assertEqual(dvar.values, ('< 0.2', '≥ 0.2')) + + dvar = FixedWidth(1, 2)(data, 0) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + dvar = FixedWidth(0.11, 2)(data, 1) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + dvar = FixedWidth(0.11, 2)(data, 2) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + self.assertRaises(TooManyIntervals, FixedWidth(0.0001, 1), data, 0) + + +class TestFixedTimeWidth(unittest.TestCase): + def test_discretization(self): + t = TimeVariable("t") + x = np.array([[t.to_val("1914"), t.to_val("1945"), np.nan], + [t.to_val("1914"), t.to_val("1914"), np.nan], + [np.nan, np.nan, np.nan], + ]).T + domain = Domain([t, TimeVariable("t2"), TimeVariable("t3")]) + data = Table.from_numpy(domain, x, None) + + dvar = FixedTimeWidth(10, 1)(data, 1) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + dvar = FixedTimeWidth(10, 2)(data, 2) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + self.assertRaises(TooManyIntervals, FixedWidth(0.0001, 1), data, 0) + + dvar = FixedTimeWidth(10, 0)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(str(y))) for y in (1920, 1930, 1940)]) + self.assertEqual(dvar.values, + ('< 1920', '1920 - 1930', '1930 - 1940', '≥ 1940')) + + dvar = FixedTimeWidth(5, 0)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(str(y))) for y in (1915, 1920, 1925, 1930, 1935, + 1940, 1945)]) + self.assertEqual(dvar.values, + ('< 1915', '1915 - 1920', '1920 - 1925', '1925 - 1930', + '1930 - 1935', '1935 - 1940', '1940 - 1945', '≥ 1945') + ) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-07-28"), t.to_val("1918-11-11")]]).T) + dvar = FixedTimeWidth(6, 1)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1915-01-01", "1915-07-01", + "1916-01-01", "1916-07-01", + "1917-01-01", "1917-07-01", + "1918-01-01", "1918-07-01")]) + self.assertEqual(dvar.values, + ('< 15 Jan', '15 Jan - Jul', '15 Jul - 16 Jan', + '16 Jan - Jul', '16 Jul - 17 Jan', '17 Jan - Jul', + '17 Jul - 18 Jan', '18 Jan - Jul', '≥ 18 Jul')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-07-28"), t.to_val("1914-11-11")]]).T) + dvar = FixedTimeWidth(6, 1)(data, 0) + np.testing.assert_almost_equal(dvar.compute_value.points, []) + + dvar = FixedTimeWidth(2, 1)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-09-01", "1914-11-01")]) + self.assertEqual(dvar.values, ('< Sep', 'Sep - Nov', '≥ Nov')) + + dvar = FixedTimeWidth(1, 1)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-08-01", "1914-09-01", + "1914-10-01", "1914-11-01")]) + self.assertEqual(dvar.values, ('< Aug', 'Aug - Sep', 'Sep - Oct', + 'Oct - Nov', '≥ Nov')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-28 10:45"), + t.to_val("1914-07-04 15:25")]]).T) + dvar = FixedTimeWidth(2, 2)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-29", "1914-07-01", + "1914-07-03")]) + self.assertEqual(dvar.values, ('< Jun 29', 'Jun 29 - Jul 01', + 'Jul 01 - Jul 03', '≥ Jul 03')) + + dvar = FixedTimeWidth(1, 2)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-29", "1914-06-30", + "1914-07-01", "1914-07-02", + "1914-07-03", "1914-07-04")]) + self.assertEqual(dvar.values, ('< Jun 29', 'Jun 29 - Jun 30', + 'Jun 30 - Jul 01', 'Jul 01 - Jul 02', + 'Jul 02 - Jul 03', 'Jul 03 - Jul 04', + '≥ Jul 04')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-12-30 22:45"), + t.to_val("1915-01-02 15:25")]]).T) + dvar = FixedTimeWidth(1, 2)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-12-31", "1915-01-01", + "1915-01-02")]) + self.assertEqual(dvar.values, ('< 14 Dec 31', + '14 Dec 31 - 15 Jan 01', + '15 Jan 01 - Jan 02', '≥ 15 Jan 02')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-28 10:45"), + t.to_val("1914-06-28 15:25")]]).T) + dvar = FixedTimeWidth(2, 3)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-28 12:00", "1914-06-28 14:00")]) + self.assertEqual(dvar.values, ('< 12:00', '12:00 - 14:00', '≥ 14:00')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-28 10:45"), + t.to_val("1914-06-28 15:25")]]).T) + dvar = FixedTimeWidth(1, 3)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-28 11:00", "1914-06-28 12:00", + "1914-06-28 13:00", "1914-06-28 14:00", + "1914-06-28 15:00")]) + self.assertEqual(dvar.values, ('< 11:00', '11:00 - 12:00', + '12:00 - 13:00', '13:00 - 14:00', + '14:00 - 15:00', '≥ 15:00')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-28 22:45"), + t.to_val("1914-06-29 03:25")]]).T) + dvar = FixedTimeWidth(1, 3)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-28 23:00", "1914-06-29 00:00", + "1914-06-29 01:00", "1914-06-29 02:00", + "1914-06-29 03:00")]) + self.assertEqual(dvar.values, ('< Jun 28 23:00', + 'Jun 28 23:00 - Jun 29 00:00', + 'Jun 29 00:00 - 01:00', + 'Jun 29 01:00 - 02:00', + 'Jun 29 02:00 - 03:00', + '≥ Jun 29 03:00')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-28 22:43"), + t.to_val("1914-06-28 23:01")]]).T) + dvar = FixedTimeWidth(5, 4)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-28 22:45", "1914-06-28 22:50", + "1914-06-28 22:55", "1914-06-28 23:00")]) + self.assertEqual(dvar.values, ('< 22:45', "22:45 - 22:50", + "22:50 - 22:55", "22:55 - 23:00", + '≥ 23:00')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-30 23:48"), + t.to_val("1914-07-01 00:06")]]).T) + dvar = FixedTimeWidth(5, 4)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-30 23:50", "1914-06-30 23:55", + "1914-07-01 00:00", "1914-07-01 00:05")]) + self.assertEqual(dvar.values, ('< Jun 30 23:50', "Jun 30 23:50 - 23:55", + "Jun 30 23:55 - Jul 01 00:00", + "Jul 01 00:00 - 00:05", '≥ Jul 01 00:05')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-29 23:48"), + t.to_val("1914-06-30 00:06")]]).T) + dvar = FixedTimeWidth(5, 4)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-29 23:50", "1914-06-29 23:55", + "1914-06-30 00:00", "1914-06-30 00:05")]) + self.assertEqual(dvar.values, ('< Jun 29 23:50', "Jun 29 23:50 - 23:55", + "Jun 29 23:55 - Jun 30 00:00", + "Jun 30 00:00 - 00:05", '≥ Jun 30 00:05')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-29 23:48:05"), + t.to_val("1914-06-29 23:51:59")]]).T) + dvar = FixedTimeWidth(1, 4)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-29 23:49", "1914-06-29 23:50", + "1914-06-29 23:51")]) + self.assertEqual(dvar.values, ('< 23:49', "23:49 - 23:50", + "23:50 - 23:51", '≥ 23:51')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-06-29 23:48:05.123"), + t.to_val("1914-06-29 23:48:33.684")]]).T) + dvar = FixedTimeWidth(10, 5)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-06-29 23:48:10", + "1914-06-29 23:48:20", + "1914-06-29 23:48:30")]), + self.assertEqual(dvar.values, ('< 23:48:10', "23:48:10 - 23:48:20", + "23:48:20 - 23:48:30", '≥ 23:48:30')) + + data = Table.from_numpy( + Domain([t]), + np.array([[t.to_val("1914-12-31 23:59:58.1"), + t.to_val("1915-01-01 00:00:01.8")]]).T) + dvar = FixedTimeWidth(1, 5)(data, 0) + np.testing.assert_almost_equal( + dvar.compute_value.points, + [int(t.to_val(y)) for y in ("1914-12-31 23:59:59", + "1915-01-01 00:00:00", + "1915-01-01 00:00:01")]), + self.assertEqual(dvar.values, ('< 23:59:59', "23:59:59 - 00:00:00", + "00:00:00 - 00:00:01", '≥ 00:00:01')) + + +class TestBinningDiscretizer(unittest.TestCase): + def test_no_data(self): + no_data = Table(Domain([ContinuousVariable("y")]), np.zeros((0, 1))) + dvar = Binning()(no_data, 0) + self.assertEqual(dvar.compute_value.points, []) + + @patch("Orange.preprocess.discretize.time_binnings") + @patch("Orange.preprocess.discretize.decimal_binnings") + @patch("Orange.preprocess.discretize.Binning._create_binned_var") + def test_call(self, _, decbin, timebin): + data = Table(Domain([ContinuousVariable("y"), TimeVariable("t")]), + np.array([[1, 2], [3, 4]])) + + Binning(5)(data, 0) + timebin.assert_not_called() + self.assertEqual(list(decbin.call_args[0][0]), [1, 3]) + decbin.reset_mock() + + Binning(5)(data, 1) + decbin.assert_not_called() + self.assertEqual(list(timebin.call_args[0][0]), [2, 4]) + + def test_binning_selection(self): + var = ContinuousVariable("y") + discretize = Binning(2) + create = discretize._create_binned_var + + binnings = [] + self.assertEqual(create(binnings, var).compute_value.points, []) + + binnings = None + self.assertEqual(create(binnings, var).compute_value.points, []) + + binnings = [ + BinDefinition(np.arange(i + 1), + [f"t{x}" for x in range(i + 1)], + [f"t{x}" for x in range(i + 1)], + 1 / i, str(i) + ) + for i in (3, 5, 10, 20) + ] + + for discretize.n in (2, 3): + self.assertEqual(create(binnings, var).values, + ('< t1', "t1 - t2", "≥ t2")) + + for discretize.n in (4, 5, 6, 7): + self.assertEqual(create(binnings, var).values, + ('< t1', "t1 - t2", "t2 - t3", "t3 - t4", "≥ t4")) + + for discretize.n in range(8, 15): + self.assertEqual(len(create(binnings, var).values), 10) + + for discretize.n in range(16, 25): + self.assertEqual(len(create(binnings, var).values), 20) # pylint: disable=redefined-builtin diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 157d5c4f5d2..81d3ea2847e 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -1,215 +1,317 @@ import re -from enum import IntEnum from collections import namedtuple -from typing import Optional, Tuple, Iterable, Union, Callable, Any +from enum import IntEnum +from typing import Optional, Tuple, Union, Callable, NamedTuple, Dict +import html +from AnyQt.QtCore import ( + Qt, QTimer, QPoint, QItemSelectionModel, QSize, QAbstractListModel +) +from AnyQt.QtGui import (QValidator, QPalette, QDoubleValidator, QIntValidator, + QColor) from AnyQt.QtWidgets import ( QListView, QHBoxLayout, QStyledItemDelegate, QButtonGroup, QWidget, - QLineEdit, QToolTip, QLabel, QApplication + QLineEdit, QToolTip, QLabel, QApplication, + QSpinBox, QSizePolicy, QRadioButton, QComboBox ) -from AnyQt.QtGui import QValidator, QPalette -from AnyQt.QtCore import Qt, QTimer, QPoint + +from Orange.widgets.gui import createAttributePixmap +from Orange.widgets.utils.itemmodels import DomainModel +from orangewidget.settings import ContextHandler, Setting, ContextSetting from orangewidget.utils.listview import ListViewSearch import Orange.data import Orange.preprocess.discretize as disc -from Orange.data import Variable -from Orange.widgets import widget, gui, settings -from Orange.widgets.utils import itemmodels, vartype, unique_everseen +from Orange.data import ContinuousVariable, DiscreteVariable, TimeVariable, \ + Domain, Table +from Orange.widgets import widget, gui +from Orange.widgets.utils import unique_everseen from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.widget import Input, Output from Orange.widgets.data.oweditdomain import FixedSizeButton -__all__ = ["OWDiscretize"] - -# 'Default' method delegates to 'method' -Default = namedtuple("Default", ["method"]) -Leave = namedtuple("Leave", []) -MDL = namedtuple("MDL", []) -EqualFreq = namedtuple("EqualFreq", ["k"]) -EqualWidth = namedtuple("EqualWidth", ["k"]) -Remove = namedtuple("Remove", []) -Custom = namedtuple("Custom", ["points"]) - - -MethodType = Union[ - Default, - Leave, - MDL, - EqualFreq, - EqualWidth, - Remove, - Custom, -] - -_dispatch = { - Default: - lambda m, data, var: _dispatch[type(m.method)](m.method, data, var), - Leave: lambda m, data, var: var, - MDL: lambda m, data, var: disc.EntropyMDL()(data, var), - EqualFreq: lambda m, data, var: disc.EqualFreq(m.k)(data, var), - EqualWidth: lambda m, data, var: disc.EqualWidth(m.k)(data, var), - Remove: lambda m, data, var: None, - Custom: - lambda m, data, var: - disc.Discretizer.create_discretized_var(var, m.points) -} -# Variable discretization state (back compat for deserialization) -DState = namedtuple( - "DState", - ["method", # discretization method - "points", # induced cut points - "disc_var"] # induced discretized variable -) +re_custom_sep = re.compile(r"\s*,\s*") +time_units = ["year", "month", "day", "week", "hour", "minute", "second"] -def is_discretized(var): - return isinstance(var.compute_value, disc.Discretizer) +def fixed_width_discretization(data, var, width): + digits = len(width) - width.index(".") - 1 if "." in width else 0 + try: + width = float(width) + except ValueError: + return "invalid width" + if width <= 0: + return "invalid width" + try: + return disc.FixedWidth(width, digits)(data, var) + except disc.TooManyIntervals: + return "too many intervals" -def variable_key(var): - return vartype(var), var.name +def fixed_time_width_discretization(data, var, width, unit): + try: + width = int(width) + except ValueError: + return "invalid width" + if width <= 0: + return "invalid width" + if unit == 3: # week + width *= 7 + unit -= unit >= 3 + try: + return disc.FixedTimeWidth(width, unit)(data, var) + except disc.TooManyIntervals: + return "too many intervals" -def button_group_reset(group): - button = group.checkedButton() - if button is not None: - group.setExclusive(False) - button.setChecked(False) - group.setExclusive(True) +def custom_discretization(data, var, points): + try: + cuts = [float(x) for x in re_custom_sep.split(points.strip())] + except ValueError: + cuts = [] + if any(x >= y for x, y in zip(cuts, cuts[1:])): + cuts = [] + if not cuts: + return "invalid cuts" + return disc.Discretizer.create_discretized_var(var, cuts) -class DiscDelegate(QStyledItemDelegate): - def initStyleOption(self, option, index): - super().initStyleOption(option, index) - state = index.data(Qt.UserRole) - var = index.data(Qt.EditRole) +class Methods(IntEnum): + Default, Keep, MDL, EqualFreq, EqualWidth, Remove, Custom, Binning, \ + FixedWidth, FixedWidthTime = range(10) + + +class MethodDesc(NamedTuple): + id_: Methods + label: str + short_desc: str + tooltip: str + function: Optional[Callable] + controls: Tuple[str, ...] = () + + +Options: Dict[Methods, MethodDesc] = { + method.id_: method + for method in ( + MethodDesc(Methods.Default, + "Use default setting", "default", + "Treat the variable as defined in 'default setting'", + None, + ()), + MethodDesc(Methods.Keep, + "Keep numeric", "keep", + "Keep the variable as is", + lambda data, var: var, + ()), + MethodDesc(Methods.MDL, + "Entropy vs. MDL", "entropy", + "Split values until MDL exceeds the entropy (Fayyad-Irani)\n" + "(requires discrete class variable)", + disc.EntropyMDL(), + ()), + MethodDesc(Methods.EqualFreq, + "Equal frequency, intervals: ", "equal freq, k={}", + "Create bins with same number of instances", + lambda data, var, k: disc.EqualFreq(k)(data, var), + ("freq_spin", )), + MethodDesc(Methods.EqualWidth, + "Equal width, intervals: ", "equal width, k={}", + "Create bins of the same width", + lambda data, var, k: disc.EqualWidth(k)(data, var), + ("width_spin", )), + MethodDesc(Methods.Remove, + "Remove", "remove", + "Remove variable", + lambda *_: None, + ()), + MethodDesc(Methods.Binning, + "Natural binning, desired bins: ", "binning, desired={}", + "Create bins with nice thresholds; " + "try matching desired number of bins", + lambda data, var, nbins: disc.Binning(nbins)(data, var), + ("binning_spin", )), + MethodDesc(Methods.FixedWidth, + "Fixed width: ", "fixed width {}", + "Create bins with the given width (not for time variables)", + fixed_width_discretization, + ("width_line", )), + MethodDesc(Methods.FixedWidthTime, + "Time interval: ", "time interval, {} {}", + "Create bins with the give width (for time variables)", + fixed_time_width_discretization, + ("width_time_line", "width_time_unit")), + MethodDesc(Methods.Custom, + "Custom: ", "custom: {}", + "Use manually specified thresholds", + custom_discretization, + ("threshold_line", )) + ) +} - if state is not None: - if isinstance(var, Variable): - fmt = var.repr_val - else: - fmt = str - extra = self.cutsText(state, fmt) - option.text = option.text + ": " + extra - - @staticmethod - def cutsText(state: DState, fmt: Callable[[Any], str] = str): - # This function has many branches, but they don't hurt readabability - # pylint: disable=too-many-branches - method = state.method - # Need a better way to distinguish discretization states - # i.e. between 'induced no points v.s. 'removed by choice' - if state.points is None and state.disc_var is not None: - points = "" - elif state.points is None: - points = "..." - elif state.points == []: - points = "" - else: - points = ", ".join(map(fmt, state.points)) - - if isinstance(method, Default): - name = None - elif isinstance(method, Leave): - name = "(leave)" - elif isinstance(method, MDL): - name = "(entropy)" - elif isinstance(method, EqualFreq): - name = "(equal frequency k={})".format(method.k) - elif isinstance(method, EqualWidth): - name = "(equal width k={})".format(method.k) - elif isinstance(method, Remove): - name = "(removed)" - elif isinstance(method, Custom): - name = "(custom)" - else: - assert False - if name is not None: - return points + " " + name - else: - return points +class VarHint(NamedTuple): + """Description for settings""" + method_id: Methods + args: Tuple[Union[str, float, int]] -#: Discretization methods -class Methods(IntEnum): - Default, Leave, MDL, EqualFreq, EqualWidth, Remove, Custom = range(7) +class DiscDesc(NamedTuple): + """Data for list view model""" + hint: VarHint + points: str + values: Tuple[str] - @staticmethod - def from_method(method): - return Methods[type(method).__name__] +KeyType = Optional[Tuple[str, bool]] +DefaultHint = VarHint(Methods.Keep, ()) +DefaultKey = None -def parse_float(string: str) -> Optional[float]: - try: - return float(string) - except ValueError: - return None +def variable_key(var: ContinuousVariable) -> KeyType: + return var.name, isinstance(var, TimeVariable) -class IncreasingNumbersListValidator(QValidator): - """ - Match a comma separated list of non-empty and increasing number strings. - - Example - ------- - >>> v = IncreasingNumbersListValidator() - >>> v.validate("", 0) # Acceptable - (2, '', 0) - >>> v.validate("1", 1) # Acceptable - (2, '1', 1) - >>> v.validate("1,,", 1) # Intermediate - (1, '1,,', 1) - """ - @staticmethod - def itersplit(string: str) -> Iterable[Tuple[int, int]]: - sepiter = re.finditer(r"(? Tuple[QValidator.State, str, int]: - state = QValidator.Acceptable - # Matches non-complete intermediate numbers (while editing) - intermediate = re.compile(r"([+-]?\s?\d*\s?\d*\.?\d*\s?\d*)") - values = [] - for start, end in self.itersplit(string): - valuestr = string[start:end].strip() - if not valuestr: - # Middle element is empty (will be fixed by fixup) - continue - value = parse_float(valuestr) - if value is None: - if intermediate.fullmatch(valuestr): - state = min(state, QValidator.Intermediate) - continue - return QValidator.Invalid, string, pos - if values and value <= values[-1]: - state = min(state, QValidator.Intermediate) +class ListViewSearch(ListViewSearch): + class DiscDelegate(QStyledItemDelegate): + def initStyleOption(self, option, index): + super().initStyleOption(option, index) + option.font.setBold(index.data(Qt.UserRole).hint is not None) + + # Same name so that we can override a private method __layout + def __init__(self, *args, **kwargs): + self.default_view = None + super().__init__(preferred_size=QSize(350, -1), *args, **kwargs) + self.setItemDelegate(self.DiscDelegate(self)) + + def select_default(self): + index = self.default_view.model().index(0) + self.default_view.selectionModel().select(index, + QItemSelectionModel.Select) + + def __layout(self): + if self.default_view is None: # __layout was called from __init__ + view = self.default_view = QListView(self) + view.setModel(DefaultDiscModel()) + view.verticalScrollBar().setDisabled(True) + view.horizontalScrollBar().setDisabled(True) + view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + font = view.font() + font.setBold(True) + view.setFont(font) + else: + view = self.default_view + + # Put the list view with default on top + margins = self.viewportMargins() + def_height = view.sizeHintForRow(0) + 2 * view.spacing() + 2 + view.setGeometry(0, 0, self.geometry().width(), def_height) + view.setFixedHeight(def_height) + + # Then search + search = self.__search + src_height = search.sizeHint().height() + size = self.size() + search.setGeometry(0, def_height + 2, size.width(), src_height) + + # Then the real list view + margins.setTop(def_height + 2 + src_height) + self.setViewportMargins(margins) + + +def format_desc(hint): + if hint is None: + return Options[Methods.Default].short_desc + desc = Options[hint.method_id].short_desc + if hint.method_id == Methods.FixedWidthTime: + width, unit = hint.args + try: + width = int(width) + except ValueError: + pass + else: + return desc.format(width, time_units[unit] + "s" * (int(width) != 1)) + return desc.format(*hint.args) + + +class DiscDomainModel(DomainModel): + def data(self, index, role=Qt.DisplayRole): + if role == Qt.ToolTipRole: + var = self[index.row()] + data = index.data(Qt.UserRole) + tip = f"{var.name}: " + values = map(html.escape, data.values) + if not data.values: + return None + if len(data.values) <= 3: + return f'

{tip}' \ + f'{",  ".join(values)}

' else: - values.append(value) - return state, string, pos + return tip + "
" \ + + "".join(f"- {value}
" for value in values) + value = super().data(index, role) + if role == Qt.DisplayRole: + hint, points, values = index.data(Qt.UserRole) + value += f" ({format_desc(hint)}){points}" + return value + + +class DefaultDiscModel(QAbstractListModel): + icon = None + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + if DefaultDiscModel.icon is None: + DefaultDiscModel.icon = createAttributePixmap("★", QColor(0, 0, 0, 0), Qt.black) + self.hint: VarHint = DefaultHint + + def rowCount(self, parent): + return 0 if parent.isValid() else 1 + + def columnCount(self, parent): + return 0 if parent.isValid() else 1 + + def data(self, index, role=Qt.DisplayRole): + if role == Qt.DisplayRole: + return "Default setting: " + format_desc(self.hint) + elif role == Qt.DecorationRole: + return DefaultDiscModel.icon + elif role == Qt.ToolTipRole: + return "Default setting for variables without specific setings" + + def setData(self, index, value, role): + if role == Qt.UserRole: + self.hint = value + self.dataChanged.emit(index, index) + else: + super().set_data(index, value, role) - def fixup(self, string): - # type: (str) -> str - """ - Fixup the input. Remove empty parts from the string. - """ - parts = [string[start: end] for start, end in self.itersplit(string)] - parts = [part for part in parts if part.strip()] - return ", ".join(parts) + +class IncreasingNumbersListValidator(QValidator): + def validate(self, string: str, pos: int) -> Tuple[QValidator.State, str, int]: + for i, c in enumerate(string, start=1): + if c not in "+-., 0123456789": + return QValidator.Invalid, string, i + prev = None + if pos == len(string) >= 2 \ + and string[-1] == " " and string[-2].isdigit(): + string = string[:-1] + ", " + pos += 1 + for valuestr in re_custom_sep.split(string.strip()): + try: + value = float(valuestr) + except ValueError: + return QValidator.Intermediate, string, pos + if prev is not None and value <= prev: + return QValidator.Intermediate, string, pos + prev = value + return QValidator.Acceptable, string, pos def show_tip( widget: QWidget, pos: QPoint, text: str, timeout=-1, - textFormat=Qt.AutoText, wordWrap=None -): + textFormat=Qt.AutoText, wordWrap=None): propname = __name__ + "::show_tip_qlabel" if timeout < 0: timeout = widget.toolTipDuration() @@ -232,6 +334,7 @@ def hide(): tip.setForegroundRole(QPalette.ToolTipText) tip.setPalette(QToolTip.palette()) tip.setFont(QApplication.font("QTipLabel")) + tip.setContentsMargins(2, 2, 2, 2) tip.timer = QTimer(tip, singleShot=True, objectName="hide-timer") tip.timer.timeout.connect(hide) widget.setProperty(propname, tip) @@ -251,109 +354,137 @@ def hide(): tip.move(pos) +class DiscretizeContextHandler(ContextHandler): + def match(self, context, data: Table): + if data is None: + return self.NO_MATCH + domain: Domain = data.domain + types = (ContinuousVariable, TimeVariable) + var_hints = context.values.get("var_hints") + if var_hints is None: # sanity check + return self.NO_MATCH + for key, hint in var_hints.items(): + if hint.method_id == Methods.MDL and not domain.has_discrete_class: + return self.NO_MATCH + if key is DefaultKey: + continue + name, tpe = key + if name not in domain or not isinstance(domain[name], types[tpe]): + return self.NO_MATCH + return self.PERFECT_MATCH + + +# These are no longer used, but needed for loading and migrating old pickles. +# We insert them into namespace instead of normally defining them, in order +# to hide it from IDE's and avoid mistakenly using them. +globals().update(dict( + DState=namedtuple( + "DState", + ["method", # discretization method + "points", # induced cut points + "disc_var"] # induced discretized variable + ), + Default=namedtuple("Default", ["method"]), + Leave=namedtuple("Leave", []), + MDL=namedtuple("MDL", []), + EqualFreq=namedtuple("EqualFreq", ["k"]), + EqualWidth=namedtuple("EqualWidth", ["k"]), + Remove=namedtuple("Remove", []), + Custom=namedtuple("Custom", ["points"]) +)) + + class OWDiscretize(widget.OWWidget): # pylint: disable=too-many-instance-attributes name = "Discretize" - description = "Discretize the numeric data features." + description = "Discretize numeric variables" category = "Transform" icon = "icons/Discretize.svg" keywords = ["bin", "categorical", "nominal", "ordinal"] priority = 2130 class Inputs: - data = Input("Data", Orange.data.Table, doc="Input data table") + data = Input("Data", Table, doc="Input data table") class Outputs: - data = Output("Data", Orange.data.Table, doc="Table with discretized features") - - settingsHandler = settings.DomainContextHandler() - settings_version = 2 - saved_var_states = settings.ContextSetting({}) + data = Output("Data", Table, doc="Table with categorical features") - #: The default method name - default_method_name = settings.Setting(Methods.EqualFreq.name) - #: The k for Equal{Freq,Width} - default_k = settings.Setting(3) - #: The default cut points for custom entry - default_cutpoints: Tuple[float, ...] = settings.Setting(()) - autosend = settings.Setting(True) + settingsHandler = DiscretizeContextHandler() + settings_version = 3 - #: Discretization methods - Default, Leave, MDL, EqualFreq, EqualWidth, Remove, Custom = list(Methods) + #: Default setting (key DefaultKey) and specific settings for variables; + # if variable is not in the dict, it uses default + var_hints: Dict[KeyType, VarHint] = ContextSetting({DefaultKey: DefaultHint}) + autosend = Setting(True) want_main_area = False - resizing_enabled = False def __init__(self): super().__init__() #: input data self.data = None - self.class_var = None - #: Current variable discretization state - self.var_state = {} - #: Saved variable discretization settings (context setting) - self.saved_var_states = {} - - self.method = Methods.Default - self.k = 5 - self.cutpoints = () - - box = gui.vBox(self.controlArea, self.tr("Default Discretization")) - self._default_method_ = 0 - self.default_bbox = rbox = gui.radioButtons( - box, self, "_default_method_", callback=self._default_disc_changed) - self.default_button_group = bg = rbox.findChild(QButtonGroup) - bg.buttonClicked[int].connect(self.set_default_method) - - rb = gui.hBox(rbox) - self.left = gui.vBox(rb) - right = gui.vBox(rb) - rb.layout().setStretch(0, 1) - rb.layout().setStretch(1, 1) - self.options = [ - (Methods.Default, self.tr("Default")), - (Methods.Leave, self.tr("Leave numeric")), - (Methods.MDL, self.tr("Entropy-MDL discretization")), - (Methods.EqualFreq, self.tr("Equal-frequency discretization")), - (Methods.EqualWidth, self.tr("Equal-width discretization")), - (Methods.Remove, self.tr("Remove numeric variables")), - (Methods.Custom, self.tr("Manual")), - ] - - for id_, opt in self.options[1:]: - t = gui.appendRadioButton(rbox, opt) - bg.setId(t, id_) - t.setChecked(id_ == self.default_method) - [right, self.left][opt.startswith("Equal")].layout().addWidget(t) - - def _intbox(parent, attr, callback): - box = gui.indentedBox(parent) - s = gui.spin( - box, self, attr, minv=2, maxv=10, label="Num. of intervals:", - callback=callback) - s.setMaximumWidth(60) + #: Cached discretized variables + self.discretized_vars: Dict[KeyType, DiscreteVariable] = {} + + box = gui.hBox(self.controlArea, True, spacing=8) + self._create_var_list(box) + self._create_buttons(box) + gui.auto_apply(self.buttonsArea, self, "autosend") + gui.rubber(self.buttonsArea) + + self.varview.select_default() + + def _create_var_list(self, box): + # If we don't elide, remove the `uniformItemSize` argument + self.varview = ListViewSearch( + selectionMode=QListView.ExtendedSelection, uniformItemSizes=True) + self.varview.setModel( + DiscDomainModel( + valid_types=(ContinuousVariable, TimeVariable), + order=DiscDomainModel.MIXED + )) + self.varview.selectionModel().selectionChanged.connect( + self._var_selection_changed) + self.varview.default_view.selectionModel().selectionChanged.connect( + self._default_selected) + self._set_default_data() + box.layout().addWidget(self.varview) + + def _create_buttons(self, box): + def intspin(): + s = QSpinBox(self) + s.setMinimum(2) + s.setMaximum(10) + s.setFixedWidth(60) s.setAlignment(Qt.AlignRight) - gui.rubber(s.box) - return box.box + s.setContentsMargins(0, 0, 0, 0) + return s, s.valueChanged - self.k_general = _intbox(self.left, "default_k", - self._default_disc_changed) - self.k_general.layout().setContentsMargins(0, 0, 0, 0) + def widthline(validator): + s = QLineEdit(self) + s.setFixedWidth(60) + s.setAlignment(Qt.AlignRight) + s.setValidator(validator) + s.setContentsMargins(0, 0, 0, 0) + return s, s.textChanged def manual_cut_editline(text="", enabled=True) -> QLineEdit: edit = QLineEdit( text=text, placeholderText="e.g. 0.0, 0.5, 1.0", - toolTip="Enter fixed discretization cut points (a comma " - "separated list of strictly increasing numbers e.g. " - "0.0, 0.5, 1.0).", + toolTip='

' + + 'Enter cut points as a comma-separate list of \n' + 'strictly increasing numbers e.g. 0.0, 0.5, 1.0).

', enabled=enabled, ) + edit.setValidator(IncreasingNumbersListValidator()) + edit.setSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.Fixed) + @edit.textChanged.connect def update(): validator = edit.validator() - if validator is not None: + if validator is not None and edit.text().strip(): state, _, _ = validator.validate(edit.text(), 0) else: state = QValidator.Acceptable @@ -375,395 +506,292 @@ def update(): show_tip(edit, p, edit.toolTip(), textFormat=Qt.RichText) else: show_tip(edit, p, "") - return edit - - self.manual_cuts_edit = manual_cut_editline( - text=", ".join(map(str, self.default_cutpoints)), - enabled=self.default_method == Methods.Custom, - ) - - def set_manual_default_cuts(): - text = self.manual_cuts_edit.text() - self.default_cutpoints = tuple( - float(s.strip()) for s in text.split(",") if s.strip()) - self._default_disc_changed() - self.manual_cuts_edit.editingFinished.connect(set_manual_default_cuts) - - validator = IncreasingNumbersListValidator() - self.manual_cuts_edit.setValidator(validator) - ibox = gui.indentedBox(right, orientation=Qt.Horizontal) - ibox.layout().addWidget(self.manual_cuts_edit) - - right.layout().addStretch(10) - self.left.layout().addStretch(10) - - self.connect_control( - "default_cutpoints", - lambda values: self.manual_cuts_edit.setText(", ".join(map(str, values))) - ) - vlayout = QHBoxLayout() - box = gui.widgetBox( - self.controlArea, "Individual Attribute Settings", - orientation=vlayout, spacing=8 - ) - - # List view with all attributes - self.varview = ListViewSearch( - selectionMode=QListView.ExtendedSelection, - uniformItemSizes=True, - ) - self.varview.setItemDelegate(DiscDelegate()) - self.varmodel = itemmodels.VariableListModel() - self.varview.setModel(self.varmodel) - self.varview.selectionModel().selectionChanged.connect( - self._var_selection_changed - ) - - vlayout.addWidget(self.varview) - # Controls for individual attr settings - self.bbox = controlbox = gui.radioButtons( - box, self, "method", callback=self._disc_method_changed - ) - vlayout.addWidget(controlbox) - self.variable_button_group = bg = controlbox.findChild(QButtonGroup) - for id_, opt in self.options[:5]: - b = gui.appendRadioButton(controlbox, opt) - bg.setId(b, id_) - - self.k_specific = _intbox(controlbox, "k", self._disc_method_changed) - - gui.appendRadioButton(controlbox, "Remove attribute", id=Methods.Remove) - b = gui.appendRadioButton(controlbox, "Manual", id=Methods.Custom) - - self.manual_cuts_specific = manual_cut_editline( - text=", ".join(map(str, self.cutpoints)), - enabled=self.method == Methods.Custom - ) - self.manual_cuts_specific.setValidator(validator) - b.toggled[bool].connect(self.manual_cuts_specific.setEnabled) - - def set_manual_cuts(): - text = self.manual_cuts_specific.text() - points = [t for t in text.split(",") if t.split()] - self.cutpoints = tuple(float(t) for t in points) - self._disc_method_changed() - self.manual_cuts_specific.editingFinished.connect(set_manual_cuts) - - self.connect_control( - "cutpoints", - lambda values: self.manual_cuts_specific.setText(", ".join(map(str, values))) - ) - ibox = gui.indentedBox(controlbox, orientation=Qt.Horizontal) - self.copy_current_to_manual_button = b = FixedSizeButton( - text="CC", toolTip="Copy the current cut points to manual mode", - enabled=False - ) - b.clicked.connect(self._copy_to_manual) - ibox.layout().addWidget(self.manual_cuts_specific) - ibox.layout().addWidget(b) - - gui.rubber(controlbox) - controlbox.setEnabled(False) - bg.button(self.method) - self.controlbox = controlbox - - gui.auto_apply(self.buttonsArea, self, "autosend") - - self._update_spin_positions() - - @property - def default_method(self) -> Methods: - return Methods[self.default_method_name] - - @default_method.setter - def default_method(self, method): - self.set_default_method(method) - - def set_default_method(self, method: Methods): - if isinstance(method, int): - method = Methods(method) - else: - method = Methods.from_method(method) - - if method != self.default_method: - self.default_method_name = method.name - self.default_button_group.button(method).setChecked(True) - self._default_disc_changed() - self.manual_cuts_edit.setEnabled(method == Methods.Custom) + return edit, edit.textChanged + + children = [] + + def button(id_, *controls, stretch=True): + layout = QHBoxLayout() + desc = Options[id_] + button = QRadioButton(desc.label) + button.setToolTip(desc.tooltip) + self.button_group.addButton(button, id_) + layout.addWidget(button) + if controls: + if stretch: + layout.addStretch(1) + for c, signal in controls: + layout.addWidget(c) + if signal is not None: + @signal.connect + def arg_changed(): + self.button_group.button(id_).setChecked(True) + self.update_hints(id_) + + children.append(layout) + button_box.layout().addLayout(layout) + return (*controls, (None, ))[0][0] + + button_box = gui.vBox(box) + button_box.layout().setSpacing(0) + self.button_group = QButtonGroup(self) + self.button_group.idClicked.connect(self.update_hints) + + button(Methods.Keep) + button(Methods.Remove) + + self.binning_spin = button(Methods.Binning, intspin()) + validator = QDoubleValidator() + validator.setBottom(0) + self.width_line = button(Methods.FixedWidth, widthline(validator)) + + self.width_time_unit = u = QComboBox(self) + u.setContentsMargins(0, 0, 0, 0) + u.addItems([unit + "(s)" for unit in time_units]) + validator = QIntValidator() + validator.setBottom(1) + self.width_time_line = button(Methods.FixedWidthTime, + widthline(validator), + (u, u.currentTextChanged)) + + self.freq_spin = button(Methods.EqualFreq, intspin()) + self.width_spin = button(Methods.EqualWidth, intspin()) + button(Methods.MDL) + + self.copy_to_custom = FixedSizeButton( + text="CC", toolTip="Copy the current cut points to manual mode") + self.copy_to_custom.clicked.connect(self._copy_to_manual) + self.threshold_line = button(Methods.Custom, + manual_cut_editline(), + (self.copy_to_custom, None), + stretch=False) + button(Methods.Default) + maxheight = max(w.sizeHint().height() for w in children) + for w in children: + w.itemAt(0).widget().setFixedHeight(maxheight) + button_box.layout().addStretch(1) @Inputs.data def set_data(self, data): self.closeContext() self.data = data + + self.var_hints = {DefaultKey: DefaultHint} + self.discretized_vars = {} + if self.data is not None: - self._initialize(data) + self.varview.model().set_domain(data.domain) self.openContext(data) - # Restore the per variable discretization settings - self._restore(self.saved_var_states) - # Complete the induction of cut points self._update_points() else: - self._clear() + self.varview.model().set_domain(None) + + self._set_default_data() + self._set_mdl_button() self.commit.now() - def _initialize(self, data): - # Initialize the default variable states for new data. - self.class_var = data.domain.class_var - cvars = [var for var in data.domain.variables - if var.is_continuous] - self.varmodel[:] = cvars - - has_disc_class = data.domain.has_discrete_class - - def set_enabled(box: QWidget, id_: Methods, state: bool): - bg = box.findChild(QButtonGroup) - b = bg.button(id_) - b.setEnabled(state) - - set_enabled(self.default_bbox, self.MDL, has_disc_class) - bg = self.bbox.findChild(QButtonGroup) - b = bg.button(Methods.MDL) - b.setEnabled(has_disc_class) - set_enabled(self.bbox, self.MDL, has_disc_class) - - # If the newly disabled MDL button is checked then change it - if not has_disc_class and self.default_method == self.MDL: - self.default_method = Methods.Leave - if not has_disc_class and self.method == self.MDL: - self.method = Methods.Default - - # Reset (initialize) the variable discretization states. - self._reset() - - def _restore(self, saved_state): - # Restore variable states from a saved_state dictionary. - def_method = self._current_default_method() - for i, var in enumerate(self.varmodel): - key = variable_key(var) - if key in saved_state: - state = saved_state[key] - if isinstance(state.method, Default): - state = DState(Default(def_method), None, None) - self._set_var_state(i, state) - - def _reset(self): - # restore the individual variable settings back to defaults. - def_method = self._current_default_method() - self.var_state = {} - for i in range(len(self.varmodel)): - state = DState(Default(def_method), None, None) - self._set_var_state(i, state) - - def _set_var_state(self, index, state): - # set the state of variable at `index` to `state`. - self.var_state[index] = state - self.varmodel.setData(self.varmodel.index(index), state, Qt.UserRole) - - def _clear(self): - self.data = None - self.varmodel[:] = [] - self.var_state = {} - self.saved_var_states = {} - self.default_button_group.button(self.MDL).setEnabled(True) - self.variable_button_group.button(self.MDL).setEnabled(True) + def _get_values(self, controls: Tuple[str]): + values = [] + for control_name in controls: + control = getattr(self, control_name) + if isinstance(control, QSpinBox): + values.append(control.value()) + elif isinstance(control, QComboBox): + values.append(control.currentIndex()) + else: + values.append(control.text()) + return tuple(values) + + def _set_values(self, controls: Tuple[str], + values: Tuple[Union[str, int, float]]): + for control_name, value in zip(controls, values): + control = getattr(self, control_name) + if isinstance(control, QSpinBox): + control.setValue(value) + elif isinstance(control, QComboBox): + control.setCurrentIndex(value) + else: + control.setText(value) + + def _set_mdl_button(self): + mdl_button = self.button_group.button(Methods.MDL) + if self.data is None or self.data.domain.has_discrete_class: + mdl_button.setEnabled(True) + else: + if mdl_button.isChecked(): + self._set_button(Methods.Keep, True) + mdl_button.setEnabled(False) + + def varkeys_for_selection(self): + model = self.varview.model() + varkeys = [variable_key(model[i]) for i in self.selected_indices()] + return varkeys or [DefaultKey] # default settings are selected + + def update_hints(self, method_id): + args = self._get_values(Options[method_id].controls) + keys = self.varkeys_for_selection() + if method_id == Methods.Default: + for key in keys: + if key in self.var_hints: + del self.var_hints[key] + else: + self.var_hints.update(dict.fromkeys(keys, VarHint(method_id, args))) + if keys == [DefaultKey]: + invalidate = set(self.discretized_vars) - set(self.var_hints) + else: + invalidate = keys + for key in invalidate: + del self.discretized_vars[key] + + if keys == [DefaultKey]: + self._set_default_data() + self._update_points() + + def _set_default_data(self): + model = self.varview.default_view.model() + model.setData(model.index(0), self.var_hints[DefaultKey], Qt.UserRole) def _update_points(self): - """ - Update the induced cut points. - """ if self.data is None: return - def induce_cuts(method, data, var): - dvar = _dispatch[type(method)](method, data, var) + def induce_cuts(data, var, hint: VarHint): + if isinstance(var, TimeVariable): + if hint.method_id in (Methods.FixedWidth, Methods.Custom): + return ": ", var + else: + if hint.method_id == Methods.FixedWidthTime: + return ": ", var + + function = Options[hint.method_id].function + dvar = function(data, var, *hint.args) + if isinstance(dvar, str): + return f" <{dvar}>", None # error if dvar is None: - # removed - return [], None + return "", None # removed elif dvar is var: - # no transformation took place - return None, var - elif is_discretized(dvar): - return dvar.compute_value.points, dvar + return "", var # no transformation + elif isinstance(dvar.compute_value, disc.Discretizer): + points = dvar.compute_value.points + if len(points) == 0: + return " ", None + return ": " + ", ".join(map(var.repr_val, points)), dvar raise ValueError - for i, var in enumerate(self.varmodel): - state = self.var_state[i] - if state.points is None and state.disc_var is None: - points, dvar = induce_cuts(state.method, self.data, var) - new_state = state._replace(points=points, disc_var=dvar) - self._set_var_state(i, new_state) - - def _current_default_method(self): - method = self.default_method - k = self.default_k - if method == Methods.Leave: - def_method = Leave() - elif method == Methods.MDL: - def_method = MDL() - elif method == Methods.EqualFreq: - def_method = EqualFreq(k) - elif method == Methods.EqualWidth: - def_method = EqualWidth(k) - elif method == Methods.Remove: - def_method = Remove() - elif method == Methods.Custom: - def_method = Custom(self.default_cutpoints) - else: - assert False - return def_method - - def _current_method(self): - if self.method == Methods.Default: - method = Default(self._current_default_method()) - elif self.method == Methods.Leave: - method = Leave() - elif self.method == Methods.MDL: - method = MDL() - elif self.method == Methods.EqualFreq: - method = EqualFreq(self.k) - elif self.method == Methods.EqualWidth: - method = EqualWidth(self.k) - elif self.method == Methods.Remove: - method = Remove() - elif self.method == Methods.Custom: - method = Custom(self.cutpoints) - else: - assert False - return method - - def _update_spin_positions(self): - kmethods = [Methods.EqualFreq, Methods.EqualWidth] - self.k_general.setDisabled(self.default_method not in kmethods) - if self.default_method == Methods.EqualFreq: - self.left.layout().insertWidget(1, self.k_general) - elif self.default_method == Methods.EqualWidth: - self.left.layout().insertWidget(2, self.k_general) - - self.k_specific.setDisabled(self.method not in kmethods) - if self.method == Methods.EqualFreq: - self.bbox.layout().insertWidget(4, self.k_specific) - elif self.method == Methods.EqualWidth: - self.bbox.layout().insertWidget(5, self.k_specific) - - def _default_disc_changed(self): - self._update_spin_positions() - method = self._current_default_method() - state = DState(Default(method), None, None) - for i, _ in enumerate(self.varmodel): - if isinstance(self.var_state[i].method, Default): - self._set_var_state(i, state) - self._update_points() - self.commit.deferred() + default_hint = self.var_hints[DefaultKey] + model = self.varview.model() + for index, var in enumerate(model): + key = variable_key(var) + if key not in self.discretized_vars: + var_hint = self.var_hints.get(key) + points, dvar = induce_cuts(self.data, var, var_hint or default_hint) + self.discretized_vars[key] = dvar + values = getattr(dvar, "values", ()) + model.setData(model.index(index), + DiscDesc(var_hint, points, values), + Qt.UserRole) - def _disc_method_changed(self): - self._update_spin_positions() - indices = self.selected_indices() - method = self._current_method() - state = DState(method, None, None) - for idx in indices: - self._set_var_state(idx, state) - self._update_points() - self._copy_to_manual_update_enabled() self.commit.deferred() def _copy_to_manual(self): - indices = self.selected_indices() - # set of all methods for the current selection - if len(indices) != 1: - return - index = indices[0] - state = self.var_state[index] - var = self.varmodel[index] - fmt = var.repr_val - points = state.points - if points is None: - points = () + varkeys = self.varkeys_for_selection() + texts = set() + for key in varkeys: + dvar = self.discretized_vars.get(key) + fmt = self.data.domain[key[0]].repr_val + if isinstance(dvar, DiscreteVariable): + text = ", ".join(map(fmt, dvar.compute_value.points)) + texts.add(text) + self.var_hints[key] = VarHint(Methods.Custom, (text, )) + del self.discretized_vars[key] + if len(texts) == 1: + self.threshold_line.setText(texts.pop()) else: - points = tuple(state.points) - state = state._replace(method=Custom(points), points=None, disc_var=None) - self._set_var_state(index, state) - self.method = Methods.Custom - self.cutpoints = points - self.manual_cuts_specific.setText(", ".join(map(fmt, points))) + self._uncheck_all_radios() self._update_points() - self.commit.deferred() - def _copy_to_manual_update_enabled(self): - indices = self.selected_indices() - methods = [self.var_state[i].method for i in indices] - self.copy_current_to_manual_button.setEnabled( - len(indices) == 1 and not isinstance(methods[0], Custom)) + def _set_button(self, method_id, checked): + self.button_group.button(method_id).setChecked(checked) - def _var_selection_changed(self, *_): - self._copy_to_manual_update_enabled() + def _default_selected(self, selected): + if not selected: + return + self.varview.selectionModel().clearSelection() + self.set_method_state([DefaultKey]) + self.enable_radios([DefaultKey]) + + def _var_selection_changed(self, selected): + if not selected: + return + self.varview.default_view.selectionModel().clearSelection() indices = self.selected_indices() # set of all methods for the current selection - methods = [self.var_state[i].method for i in indices] - - def key(method): - if isinstance(method, Default): - return Default, (None, ) - return type(method), tuple(method) - - mset = list(unique_everseen(methods, key=key)) - - self.controlbox.setEnabled(len(mset) > 0) + model = self.varview.model() + keys = [variable_key(model[i]) for i in indices] + self.set_method_state(keys) + self.enable_radios(keys) + + def enable_radios(self, keys): + def set_enabled(method_id, value): + self.button_group.button(method_id).setEnabled(value) + for control_name in Options[method_id].controls: + getattr(self, control_name).setEnabled(value) + + if keys == [DefaultKey]: + set_enabled(Methods.Default, False) + set_enabled(Methods.FixedWidth, True) + set_enabled(Methods.FixedWidthTime, True) + set_enabled(Methods.Custom, True) + else: + set_enabled(Methods.Default, True) + vars_ = [self.data.domain[name] for name, _ in keys] + no_time = not any(isinstance(var, TimeVariable) for var in vars_) + set_enabled(Methods.FixedWidth, no_time) + set_enabled(Methods.Custom, no_time) + set_enabled(Methods.FixedWidthTime, + all(isinstance(var, TimeVariable) for var in vars_)) + + def set_method_state(self, keys): + mset = list(unique_everseen(map(self.var_hints.get, keys))) if len(mset) == 1: - method = mset.pop() - self.method = Methods.from_method(method) - if isinstance(method, (EqualFreq, EqualWidth)): - self.k = method.k - elif isinstance(method, Custom): - self.cutpoints = method.points + if mset == [None]: + method_id, args = Methods.Default, () + else: + method_id, args = mset.pop() + method = Options[method_id] + self._set_button(method_id, True) + self._set_values(method.controls, args) + if method_id != Methods.Custom: + self.threshold_line.setText("") else: - # deselect the current button - self.method = -1 - bg = self.controlbox.group - button_group_reset(bg) - self._update_spin_positions() + self._uncheck_all_radios() + + def _uncheck_all_radios(self): + group = self.button_group + button = group.checkedButton() + if button is not None: + group.setExclusive(False) + button.setChecked(False) + group.setExclusive(True) def selected_indices(self): rows = self.varview.selectionModel().selectedRows() return [index.row() for index in rows] - def method_for_index(self, index): - state = self.var_state[index] - return state.method - - def discretized_var(self, index): - # type: (int) -> Optional[Orange.data.DiscreteVariable] - state = self.var_state[index] - if state.disc_var is not None and state.points == []: - # Removed by MDL Entropy - return None - else: - return state.disc_var - def discretized_domain(self): - """ - Return the current effective discretized domain. - """ + def disc_var(var: ContinuousVariable) -> Optional[DiscreteVariable]: + return self.discretized_vars.get(variable_key(var), var) + if self.data is None: return None - # a mapping of all applied changes for variables in `varmodel` - mapping = {var: self.discretized_var(i) - for i, var in enumerate(self.varmodel)} - - def disc_var(source): - return mapping.get(source, source) - - # map the full input domain to the new variables (where applicable) - attributes = [disc_var(v) for v in self.data.domain.attributes] + attributes = (disc_var(v) for v in self.data.domain.attributes) attributes = [v for v in attributes if v is not None] - class_vars = [disc_var(v) for v in self.data.domain.class_vars] + class_vars = (disc_var(v) for v in self.data.domain.class_vars) class_vars = [v for v in class_vars if v is not None] - domain = Orange.data.Domain( - attributes, class_vars, metas=self.data.domain.metas - ) - return domain + return Domain(attributes, class_vars, metas=self.data.domain.metas) @gui.deferred def commit(self): @@ -773,31 +801,62 @@ def commit(self): output = self.data.transform(domain) self.Outputs.data.send(output) - def storeSpecificSettings(self): - super().storeSpecificSettings() - self.saved_var_states = { - variable_key(var): - self.var_state[i]._replace(points=None, disc_var=None) - for i, var in enumerate(self.varmodel) - } - def send_report(self): - self.report_items(( - ("Default method", self.options[self.default_method][1]),)) - if self.varmodel: - self.report_items("Thresholds", [ - (var.name, - DiscDelegate.cutsText(self.var_state[i], var.repr_val) or "leave numeric") - for i, var in enumerate(self.varmodel)]) + dmodel = self.varview.default_view.model() + desc = dmodel.data(dmodel.index(0)) + self.report_items((tuple(desc.split(": ", maxsplit=1)), )) + model = self.varview.model() + reported = [] + for row in range(model.rowCount()): + name = model[row].name + desc = model.data(model.index(row), Qt.UserRole) + if desc.hint is not None: + name = f"{name} ({format_desc(desc.hint)})" + reported.append((name, ', '.join(desc.values))) + self.report_items("Variables", reported) @classmethod - def migrate_settings(cls, settings, version): # pylint: disable=redefined-outer-name + def migrate_settings(cls, settings, version): if version is None or version < 2: # was stored as int indexing Methods (but offset by 1) default = settings.pop("default_method", 0) default = Methods(default + 1) settings["default_method_name"] = default.name + if version is None or version < 3: + method_name = settings.pop("default_method_name", + DefaultHint.method_id.name) + k = settings.pop("default_k", 3) + cut_points = settings.pop("default_cutpoints", ()) + + method_id = getattr(Methods, method_name) + if method_id in (Methods.EqualFreq, Methods.EqualWidth): + args = (k, ) + elif method_id == Methods.Custom: + args = (cut_points, ) + else: + args = () + default_hint = VarHint(method_id, args) + for context in settings.get("context_settings", []): + values = context.values + if "saved_var_states" not in values: + continue + var_states, _ = values.pop("saved_var_states") + var_hints = {DefaultKey: default_hint} + for (tpe, name), dstate in var_states.items(): + key = (name, tpe == 4) # time variable == 4 + method = dstate.method + method_name = type(method).__name__.replace("Leave", "Keep") + if method_name == "Default": + continue + if method_name == "Custom": + args = (", ".join(f"{x:g}" for x in method.points), ) + else: + args = tuple(method) + var_hints[key] = VarHint(getattr(Methods, method_name), args) + values["var_hints"] = var_hints + if __name__ == "__main__": # pragma: no cover - WidgetPreview(OWDiscretize).run(Orange.data.Table("brown-selected")) + #WidgetPreview(OWDiscretize).run(Table("/Users/janez/Downloads/banking-crises.tab")) + WidgetPreview(OWDiscretize).run(Table("heart_disease")) diff --git a/Orange/widgets/data/tests/test_owdiscretize.py b/Orange/widgets/data/tests/test_owdiscretize.py index 61a16b115c9..0dd7dd83323 100644 --- a/Orange/widgets/data/tests/test_owdiscretize.py +++ b/Orange/widgets/data/tests/test_owdiscretize.py @@ -1,17 +1,23 @@ # Test methods with long descriptive names can omit docstrings # pylint: disable=missing-docstring,unsubscriptable-object,protected-access import unittest +from functools import partial +from unittest.mock import patch -from AnyQt.QtCore import Qt, QPoint -from AnyQt.QtWidgets import QWidget, QApplication, QStyleOptionViewItem +from AnyQt.QtCore import QPoint +from AnyQt.QtWidgets import QWidget, QApplication -from Orange.data import Table, DiscreteVariable +from Orange.data import Table, ContinuousVariable, TimeVariable +from Orange.preprocess.discretize import TooManyIntervals from Orange.widgets.data.owdiscretize import OWDiscretize, Default, EqualFreq, \ - Remove, Leave, Custom, IncreasingNumbersListValidator, DiscDelegate, MDL, \ - EqualWidth, DState, show_tip + Remove, Leave, Custom, IncreasingNumbersListValidator, MDL, \ + EqualWidth, DState, show_tip, VarHint, Methods, DefaultKey, \ + fixed_width_discretization, fixed_time_width_discretization, \ + custom_discretization, variable_key, DefaultHint from Orange.widgets.tests.base import WidgetTest from Orange.widgets.tests.base import GuiTest -from Orange.widgets.utils.itemmodels import select_row, VariableListModel +from Orange.widgets.utils.itemmodels import select_row +from orangewidget.settings import Context class TestOWDiscretize(WidgetTest): @@ -24,10 +30,8 @@ def test_empty_data(self): widget = self.widget self.send_signal(self.widget.Inputs.data, Table.from_domain(data.domain)) - for m in (OWDiscretize.Leave, OWDiscretize.MDL, OWDiscretize.EqualFreq, - OWDiscretize.EqualWidth, OWDiscretize.Remove, - OWDiscretize.Custom): - widget.default_method = m + for m in range(len(Methods)): + widget.var_hints = {DefaultKey: VarHint(m, ())} widget.commit.now() self.assertIsNotNone(self.get_output(widget.Outputs.data)) @@ -68,12 +72,6 @@ def test_select_method(self): self.assertIsInstance(widget.method_for_index(0), Default) self.assertIsInstance(widget.method_for_index(2), Default) - def test_migration(self): - w = self.create_widget(OWDiscretize, stored_settings={ - "default_method": 0 - }) - self.assertEqual(w.default_method, OWDiscretize.Leave) - def test_manual_cuts_edit(self): widget = self.widget data = Table("iris")[::5] @@ -102,75 +100,119 @@ def test_manual_cuts_edit(self): ledit.editingFinished.emit() self.assertEqual(widget.method_for_index(0), Custom(())) - def test_manual_cuts_copy(self): - widget = self.widget - data = Table("iris")[::5] - self.send_signal(self.widget.Inputs.data, data) - view = widget.varview - select_row(view, 0) - varbg = widget.variable_button_group - varbg.button(OWDiscretize.EqualWidth).click() - v = widget.discretized_var(0) - points = tuple(v.compute_value.points) - cc_button = widget.copy_current_to_manual_button - cc_button.click() - self.assertEqual(widget.method_for_index(0), Custom(points)) - self.assertEqual(varbg.checkedId(), OWDiscretize.Custom) - def test_report(self): widget = self.widget data = Table("iris")[::5] self.send_signal(widget.Inputs.data, data) widget.send_report() + def test_all(self): + data = Table("brown-selected") + + w = self.create_widget( + OWDiscretize, + dict(context_settings=[Context(values={"var_hints": + {None: VarHint(Methods.EqualFreq, (3,)), + ('alpha 0', False): VarHint(Methods.Keep, ()), + ('alpha 7', False): VarHint(Methods.Remove, ()), + ('alpha 14', False): VarHint(Methods.Binning, (2, )), + ('alpha 21', False): VarHint(Methods.FixedWidth, ("0.05", )), + ('alpha 28', False): VarHint(Methods.EqualFreq, (4, )), + ('alpha 35', False): VarHint(Methods.MDL, ()), + ('alpha 42', False): VarHint(Methods.Custom, ("0, 0.125", )), + ('alpha 49', False): VarHint(Methods.MDL, ())}})])) + + self.send_signal(w.Inputs.data, data) + + self.assertTrue(w.button_group.button(Methods.MDL).isEnabled()) + self.assertEqual(w.varview.default_view.model().hint, + VarHint(Methods.EqualFreq, (3, ))) + + out = self.get_output(w.Outputs.data) + dom = out.domain + self.assertIsInstance(dom["alpha 0"], ContinuousVariable) + self.assertNotIn("alpha 7", dom) + self.assertEqual(dom["alpha 14"].values, ('< 0', '≥ 0')) + self.assertEqual(dom["alpha 21"].values, + ('< -0.15', "-0.15 - -0.10", "-0.10 - -0.05", + "-0.05 - 0.00", "0.00 - 0.05", "0.05 - 0.10", + '≥ 0.10')) + self.assertEqual(len(dom["alpha 28"].values), 4) + self.assertNotIn("alpha 35", dom) # removed by MDL + self.assertEqual(dom["alpha 42"].values, ('< 0', '0 - 0.125', '≥ 0.125')) + self.assertEqual(len(dom["alpha 49"].values), 2) + + self.send_signal(w.Inputs.data, None) + self.assertIsNone(self.get_output(w.Outputs.data)) + self.assertIsNone(w.data) + self.assertEqual(list(w.var_hints), [DefaultKey]) + self.assertEqual(w.discretized_vars, {}) + self.assertEqual(w.varview.default_view.model().hint, DefaultHint) + self.assertEqual(len(w.varview.model()), 0) + + self.send_signal(w.Inputs.data, data) + self.assertIsNotNone(self.get_output(w.Outputs.data)) + w.button_group.button(Methods.MDL).setChecked(True) + self.assertTrue(w.button_group.button(Methods.MDL).isEnabled()) + self.assertTrue(w.button_group.button(Methods.MDL).isChecked()) + + self.send_signal(w.Inputs.data, data[:, 0]) + self.assertFalse(w.button_group.button(Methods.MDL).isEnabled()) + self.assertFalse(w.button_group.button(Methods.MDL).isChecked()) + + self.send_signal(w.Inputs.data, data) + self.assertTrue(w.button_group.button(Methods.MDL).isEnabled()) + + def test_migration_2_3(self): + context_values = { + 'saved_var_states': + ({(2, 'age'): DState(method=Leave(), points=None, disc_var=None), + (2, 'rest SBP'): DState(method=EqualWidth(k=4), points=None, disc_var=None), + (2, 'cholesterol'): DState(method=EqualFreq(k=6), points=None, disc_var=None), + (4, 'max HR'): DState(method=Custom(points=(1.0, 2.0, 3.0)), points=None, disc_var=None), + (2, 'ST by exercise'): DState(method=MDL(), points=None, disc_var=None), + (2, 'major vessels colored'): DState(method=Default(method=EqualFreq(k=3)), points=None, disc_var=None)}, -2), + '__version__': 2} + + settings = {'autosend': True, 'controlAreaVisible': True, + 'default_cutpoints': (), 'default_k': 3, + 'default_method_name': 'EqualFreq', + '__version__': 2, + "context_settings": [Context(values=context_values)]} + + OWDiscretize.migrate_settings(settings, 2) + self.assertNotIn("default_method_name", settings) + self.assertNotIn("default_k", settings) + self.assertNotIn("default_cutpoints", settings) + values = settings["context_settings"][0].values + self.assertNotIn("saved_var_states", values) + self.assertEqual( + values["var_hints"], + {None: VarHint(Methods.EqualFreq, (3,)), + ('ST by exercise', False): VarHint(Methods.MDL, ()), + ('age', False): VarHint(Methods.Keep, ()), + ('cholesterol', False): VarHint(Methods.EqualFreq, (6, )), + ('max HR', True): VarHint(Methods.Custom, (('1, 2, 3'), )), + ('rest SBP', False): VarHint(Methods.EqualWidth, (4,))}) + class TestValidator(unittest.TestCase): def test_validate(self): v = IncreasingNumbersListValidator() - self.assertEqual(v.validate("", 0), (v.Acceptable, '', 0)) + self.assertEqual(v.validate("", 0), (v.Intermediate, '', 0)) self.assertEqual(v.validate("1", 1), (v.Acceptable, '1', 1)) - self.assertEqual(v.validate(",", 0), (v.Acceptable, ',', 0)) + self.assertEqual(v.validate(",", 0), (v.Intermediate, ',', 0)) self.assertEqual(v.validate("-", 0), (v.Intermediate, '-', 0)) - self.assertEqual(v.validate("1,,", 1), (v.Acceptable, '1,,', 1)) - self.assertEqual(v.validate("1,a,", 1), (v.Invalid, '1,a,', 1)) + self.assertEqual(v.validate("1,,", 1), (v.Intermediate, '1,,', 1)) + self.assertEqual(v.validate("1,a,", 1), (v.Invalid, '1,a,', 3)) self.assertEqual(v.validate("a", 1), (v.Invalid, 'a', 1)) self.assertEqual(v.validate("1,1", 0), (v.Intermediate, '1,1', 0)) self.assertEqual(v.validate("1,12", 0), (v.Acceptable, '1,12', 0)) - def test_fixup(self): - v = IncreasingNumbersListValidator() - self.assertEqual(v.fixup(""), "") - self.assertEqual(v.fixup("1,,2"), "1, 2") - self.assertEqual(v.fixup("1,,"), "1") - self.assertEqual(v.fixup("1,"), "1") - self.assertEqual(v.fixup(",1"), "1") - self.assertEqual(v.fixup(","), "") - - -class TestDelegate(GuiTest): - def test_delegate(self): - cases = ( - (DState(Default(Leave()), None, None), ""), - (DState(Leave(), None, None), "(leave)"), - (DState(MDL(), [1], None), "(entropy)"), - (DState(MDL(), [], None), ""), - (DState(EqualFreq(2), [1], None), "(equal frequency k=2)"), - (DState(EqualWidth(2), [1], None), "(equal width k=2)"), - (DState(Remove(), None, None), "(removed)"), - (DState(Custom([1]), None, None), "(custom)"), - ) - delegate = DiscDelegate() - var = DiscreteVariable("C", ("a", "b")) - model = VariableListModel() - model.append(var) - for state, text in cases: - model.setData(model.index(0), state, Qt.UserRole) - option = QStyleOptionViewItem() - delegate.initStyleOption(option, model.index(0)) - self.assertIn(text, option.text) - - -class TestShowTip(GuiTest): + self.assertEqual(v.validate("1, 2 ", 5), (v.Intermediate, "1, 2, ", 6)) + + +class TestUtils(GuiTest): def test_show_tip(self): w = QWidget() show_tip(w, QPoint(100, 100), "Ha Ha") @@ -185,3 +227,60 @@ def test_show_tip(self): self.assertTrue(label.text() == "Ha") show_tip(w, QPoint(100, 100), "") self.assertFalse(label.isVisible()) + + def test_fixed_width_disc(self): + fw = partial(fixed_width_discretization, None, None) + for arg in ("", "5.3.1", "abc"): + self.assertIsInstance(fw(arg), str) + + with patch("Orange.preprocess.discretize.FixedWidth") as disc: + self.assertNotIsInstance(fw("5.13"), str) + disc.assert_called_with(5.13, 2) + + self.assertNotIsInstance(fw("5"), str) + disc.assert_called_with(5, 0) + + with patch("Orange.preprocess.discretize.FixedWidth", + side_effect=TooManyIntervals): + self.assertIsInstance(fw("42"), str) + + def test_fixed_time_width_disc(self): + ftw = partial(fixed_time_width_discretization, None, None) + + for arg in ("", "5.3.1", "5.3", "abc"): + self.assertIsInstance(ftw(arg, 1), str) + + with patch("Orange.preprocess.discretize.FixedTimeWidth") as disc: + self.assertNotIsInstance(ftw("5", 2), str) + disc.assert_called_with(5, 2) + + self.assertNotIsInstance(ftw("5", 3), str) + disc.assert_called_with(35, 2) + + self.assertNotIsInstance(ftw("5", 4), str) + disc.assert_called_with(5, 3) + + with patch("Orange.preprocess.discretize.FixedTimeWidth", + side_effect=TooManyIntervals): + self.assertIsInstance(ftw("42", 3), str) + + def test_custom_discretization(self): + cd = partial(custom_discretization, None, None) + + for arg in ("", "4 5", "2, 1, 5", "1, foo, 13"): + self.assertIsInstance(cd(arg), str) + + with patch("Orange.preprocess.discretize.Discretizer." + "create_discretized_var") as disc: + cd("1, 1.25, 1.5, 4") + disc.assert_called_with(None, [1, 1.25, 1.5, 4]) + + def test_var_key(self): + self.assertEqual(variable_key(ContinuousVariable("foo")), + ("foo", False)) + self.assertEqual(variable_key(TimeVariable("bar")), + ("bar", True)) + + +if __name__ == "__main__": + unittest.main() \ No newline at end of file From 0a809227c494387fa88a6bb26188cdf38becf9ce Mon Sep 17 00:00:00 2001 From: janezd Date: Thu, 31 Mar 2022 22:45:05 +0200 Subject: [PATCH 2/9] OWDiscretize: Tidying up --- Orange/preprocess/discretize.py | 13 +- Orange/preprocess/tests/test_discretize.py | 9 +- Orange/widgets/data/owdiscretize.py | 576 +++++++++++------- .../widgets/data/tests/test_owdiscretize.py | 44 +- 4 files changed, 401 insertions(+), 241 deletions(-) diff --git a/Orange/preprocess/discretize.py b/Orange/preprocess/discretize.py index 3c50fbb4d7c..83717c3adfe 100644 --- a/Orange/preprocess/discretize.py +++ b/Orange/preprocess/discretize.py @@ -100,8 +100,8 @@ def __init__(self, var, points): self.points = points def __call__(self): - return 'width_bucket(%s, ARRAY%s::double precision[])' % ( - self.var.to_sql(), str(self.points)) + return f'width_bucket({self.var.to_sql()}, ' \ + f'ARRAY{str(self.points)}::double precision[])' class SingleValueSql: @@ -208,10 +208,10 @@ def __call__(self, data, attribute): values = values.X if values.X.size else values.Y points = [] if values.size: - min, max = ut.nanmin(values), ut.nanmax(values) - if not np.isnan(min): - minf = int(1 + np.floor(min / self.width)) - maxf = int(1 + np.floor(max / self.width)) + mn, mx = ut.nanmin(values), ut.nanmax(values) + if not np.isnan(mn): + minf = int(1 + np.floor(mn / self.width)) + maxf = int(1 + np.floor(mx / self.width)) if maxf - minf - 1 >= 100: raise TooManyIntervals points = [i * self.width for i in range(minf, maxf)] @@ -258,6 +258,7 @@ def no_common(a, b): if common + i == 2: i -= 1 return b[i:] + return b # can't come here (unless a == b?!) if not labels: diff --git a/Orange/preprocess/tests/test_discretize.py b/Orange/preprocess/tests/test_discretize.py index 6d5d07e2d4b..b18cf716901 100644 --- a/Orange/preprocess/tests/test_discretize.py +++ b/Orange/preprocess/tests/test_discretize.py @@ -1,8 +1,8 @@ # File contains some long lines; breaking them would decrease readability -# pylint: disable=line-too-long +# pylint: disable=line-too-long,too-many-lines,protected-access import calendar import unittest -from unittest.mock import patch, Mock +from unittest.mock import patch from time import struct_time, mktime import numpy as np @@ -251,7 +251,7 @@ def test_discretization(self): dvar.compute_value.points, [int(t.to_val(y)) for y in ("1914-06-29 23:48:10", "1914-06-29 23:48:20", - "1914-06-29 23:48:30")]), + "1914-06-29 23:48:30")]) self.assertEqual(dvar.values, ('< 23:48:10', "23:48:10 - 23:48:20", "23:48:20 - 23:48:30", '≥ 23:48:30')) @@ -264,7 +264,7 @@ def test_discretization(self): dvar.compute_value.points, [int(t.to_val(y)) for y in ("1914-12-31 23:59:59", "1915-01-01 00:00:00", - "1915-01-01 00:00:01")]), + "1915-01-01 00:00:01")]) self.assertEqual(dvar.values, ('< 23:59:59', "23:59:59 - 00:00:00", "00:00:00 - 00:00:01", '≥ 00:00:01')) @@ -294,6 +294,7 @@ def test_call(self, _, decbin, timebin): def test_binning_selection(self): var = ContinuousVariable("y") discretize = Binning(2) + # pylint: disable=redefined-outer-name create = discretize._create_binned_var binnings = [] diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 81d3ea2847e..1d32a815734 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -1,31 +1,26 @@ import re -from collections import namedtuple -from enum import IntEnum -from typing import Optional, Tuple, Union, Callable, NamedTuple, Dict import html +from enum import IntEnum +from typing import Optional, Tuple, Union, Callable, NamedTuple, Dict, List from AnyQt.QtCore import ( - Qt, QTimer, QPoint, QItemSelectionModel, QSize, QAbstractListModel -) -from AnyQt.QtGui import (QValidator, QPalette, QDoubleValidator, QIntValidator, - QColor) + Qt, QTimer, QPoint, QItemSelectionModel, QSize, QAbstractListModel) +from AnyQt.QtGui import ( + QValidator, QPalette, QDoubleValidator, QIntValidator, QColor) from AnyQt.QtWidgets import ( QListView, QHBoxLayout, QStyledItemDelegate, QButtonGroup, QWidget, QLineEdit, QToolTip, QLabel, QApplication, - QSpinBox, QSizePolicy, QRadioButton, QComboBox -) + QSpinBox, QSizePolicy, QRadioButton, QComboBox) -from Orange.widgets.gui import createAttributePixmap -from Orange.widgets.utils.itemmodels import DomainModel from orangewidget.settings import ContextHandler, Setting, ContextSetting -from orangewidget.utils.listview import ListViewSearch +from orangewidget.utils import listview -import Orange.data +from Orange.data import ( + ContinuousVariable, DiscreteVariable, TimeVariable, Domain, Table, Variable) import Orange.preprocess.discretize as disc -from Orange.data import ContinuousVariable, DiscreteVariable, TimeVariable, \ - Domain, Table from Orange.widgets import widget, gui from Orange.widgets.utils import unique_everseen +from Orange.widgets.utils.itemmodels import DomainModel from Orange.widgets.utils.widgetpreview import WidgetPreview from Orange.widgets.widget import Input, Output from Orange.widgets.data.oweditdomain import FixedSizeButton @@ -33,39 +28,92 @@ re_custom_sep = re.compile(r"\s*,\s*") time_units = ["year", "month", "day", "week", "hour", "minute", "second"] +INVALID_WIDTH = "invalid width" +TOO_MANY_INTERVALS = "too many intervals" + + +def _fixed_width_discretization( + data: Table, + var: Union[ContinuousVariable, str, int], + width: str) -> Union[DiscreteVariable, str]: + """ + Discretize numeric variable with fixed bin width. Used in method definition. + Width is given as string (coming from line edit). The labels for the new + variable will have the same number of digits; this is more appropriate + than the number of digits in the original variable, which may be too large. -def fixed_width_discretization(data, var, width): + Args: + data: data used to deduce the interval of values + var: variable to discretize + width: interval width + + Returns: + Discrete variable, if successful; a string with error otherwise + """ digits = len(width) - width.index(".") - 1 if "." in width else 0 try: width = float(width) except ValueError: - return "invalid width" + return INVALID_WIDTH if width <= 0: - return "invalid width" + return INVALID_WIDTH try: return disc.FixedWidth(width, digits)(data, var) except disc.TooManyIntervals: - return "too many intervals" + return TOO_MANY_INTERVALS + + +def _fixed_time_width_discretization( + data: Table, + var: Union[TimeVariable, str, int], + width: str, unit: int) -> Union[DiscreteVariable]: + """ + Discretize time variable with fixed bin width. Used in method definition. + + Width is given as string (coming from line edit). + Args: + data: data used to deduce the interval of values + var: variable to discretize + width: interval width + unit: 0 = year, 1 = month, 2 = week, 3 = day, 4 = hour, 5 = min, 6 = sec -def fixed_time_width_discretization(data, var, width, unit): + Returns: + Discrete variable, if successful; a string with error otherwise + """ try: width = int(width) except ValueError: - return "invalid width" + return INVALID_WIDTH if width <= 0: - return "invalid width" + return INVALID_WIDTH if unit == 3: # week width *= 7 unit -= unit >= 3 try: return disc.FixedTimeWidth(width, unit)(data, var) except disc.TooManyIntervals: - return "too many intervals" + return TOO_MANY_INTERVALS + + +def _custom_discretization( + _, + var: Union[ContinuousVariable, str, int], + points: str) -> Union[DiscreteVariable, str]: + """ + Discretize variable using custom thresholds. Used in method definition. + + Thresholds are given as string (coming from line edit). + Args: + data: data used to deduce the interval of values + var: variable to discretize + points: thresholds -def custom_discretization(data, var, points): + Returns: + Discrete variable, if successful; a string with error otherwise + """ try: cuts = [float(x) for x in re_custom_sep.split(points.strip())] except ValueError: @@ -78,17 +126,22 @@ def custom_discretization(data, var, points): class Methods(IntEnum): + # pylint: disable=invalid-name Default, Keep, MDL, EqualFreq, EqualWidth, Remove, Custom, Binning, \ FixedWidth, FixedWidthTime = range(10) class MethodDesc(NamedTuple): - id_: Methods - label: str - short_desc: str - tooltip: str - function: Optional[Callable] - controls: Tuple[str, ...] = () + """ + Definitions of all methods; used for creation of interface and calling + """ + id_: Methods # Method id + label: str # Label used for radio button + short_desc: str # Short descriptions for list views + tooltip: str # Tooltip for radio button + # Discretization function, see, e.g. fixed_width_discretization + function: Optional[Callable[..., Union[DiscreteVariable, str]]] + controls: Tuple[str, ...] = () # Widget attributes with related ux controls Options: Dict[Methods, MethodDesc] = { @@ -134,17 +187,17 @@ class MethodDesc(NamedTuple): MethodDesc(Methods.FixedWidth, "Fixed width: ", "fixed width {}", "Create bins with the given width (not for time variables)", - fixed_width_discretization, + _fixed_width_discretization, ("width_line", )), MethodDesc(Methods.FixedWidthTime, "Time interval: ", "time interval, {} {}", "Create bins with the give width (for time variables)", - fixed_time_width_discretization, + _fixed_time_width_discretization, ("width_time_line", "width_time_unit")), MethodDesc(Methods.Custom, "Custom: ", "custom: {}", "Use manually specified thresholds", - custom_discretization, + _custom_discretization, ("threshold_line", )) ) } @@ -169,34 +222,53 @@ class DiscDesc(NamedTuple): def variable_key(var: ContinuousVariable) -> KeyType: + """Key for that variable in var_hints and discretized_vars""" return var.name, isinstance(var, TimeVariable) -class ListViewSearch(ListViewSearch): +class ListViewSearch(listview.ListViewSearch): + """ + A list view with two components shown above it: + - a listview containing a single item representing default settings + - a filter for search + + The class is based on listview.ListViewSearch and needs to have the same + name in order to override its private method __layout. + + Inherited __init__ calls __layout, so `default_view` must be constructed + there. Construction before calling super().__init__ doesn't work because + PyQt does not allow it. + """ class DiscDelegate(QStyledItemDelegate): + """ + A delegate that shows items (variables) with specific settings in bold + """ def initStyleOption(self, option, index): super().initStyleOption(option, index) option.font.setBold(index.data(Qt.UserRole).hint is not None) - # Same name so that we can override a private method __layout def __init__(self, *args, **kwargs): self.default_view = None super().__init__(preferred_size=QSize(350, -1), *args, **kwargs) self.setItemDelegate(self.DiscDelegate(self)) def select_default(self): + """Select the item representing default settings""" index = self.default_view.model().index(0) - self.default_view.selectionModel().select(index, - QItemSelectionModel.Select) + self.default_view.selectionModel().select( + index, QItemSelectionModel.Select) + # pylint: disable=unused-private-member def __layout(self): if self.default_view is None: # __layout was called from __init__ view = self.default_view = QListView(self) view.setModel(DefaultDiscModel()) view.verticalScrollBar().setDisabled(True) view.horizontalScrollBar().setDisabled(True) - view.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) - view.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + view.setHorizontalScrollBarPolicy( + Qt.ScrollBarPolicy.ScrollBarAlwaysOff) + view.setVerticalScrollBarPolicy( + Qt.ScrollBarPolicy.ScrollBarAlwaysOff) font = view.font() font.setBold(True) view.setFont(font) @@ -220,7 +292,8 @@ def __layout(self): self.setViewportMargins(margins) -def format_desc(hint): +def format_desc(hint: VarHint) -> str: + """Describe the method and its parameters; used in list views and report""" if hint is None: return Options[Methods.Default].short_desc desc = Options[hint.method_id].short_desc @@ -236,6 +309,12 @@ def format_desc(hint): class DiscDomainModel(DomainModel): + """ + Domain model that adds description of discretization methods and thresholds + + Also provides a tooltip that shows bins, that is, labels of the discretized + variable. + """ def data(self, index, role=Qt.DisplayRole): if role == Qt.ToolTipRole: var = self[index.row()] @@ -258,27 +337,34 @@ def data(self, index, role=Qt.DisplayRole): class DefaultDiscModel(QAbstractListModel): + """ + A model used for showing "Default settings" above the list view with var + """ icon = None def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if DefaultDiscModel.icon is None: - DefaultDiscModel.icon = createAttributePixmap("★", QColor(0, 0, 0, 0), Qt.black) + DefaultDiscModel.icon = gui.createAttributePixmap( + "★", QColor(0, 0, 0, 0), Qt.black) self.hint: VarHint = DefaultHint - def rowCount(self, parent): + @staticmethod + def rowCount(parent): return 0 if parent.isValid() else 1 - def columnCount(self, parent): + @staticmethod + def columnCount(parent): return 0 if parent.isValid() else 1 - def data(self, index, role=Qt.DisplayRole): + def data(self, _, role=Qt.DisplayRole): if role == Qt.DisplayRole: return "Default setting: " + format_desc(self.hint) elif role == Qt.DecorationRole: return DefaultDiscModel.icon elif role == Qt.ToolTipRole: return "Default setting for variables without specific setings" + return None def setData(self, index, value, role): if role == Qt.UserRole: @@ -289,7 +375,14 @@ def setData(self, index, value, role): class IncreasingNumbersListValidator(QValidator): - def validate(self, string: str, pos: int) -> Tuple[QValidator.State, str, int]: + """ + A validator for custom thresholds + + Requires a string with increasing comma-separated values. If the string + ends with number followed by space, it inserts a comma. + """ + @staticmethod + def validate(string: str, pos: int) -> Tuple[QValidator.State, str, int]: for i, c in enumerate(string, start=1): if c not in "+-., 0123456789": return QValidator.Invalid, string, i @@ -308,54 +401,55 @@ def validate(self, string: str, pos: int) -> Tuple[QValidator.State, str, int]: prev = value return QValidator.Acceptable, string, pos + @staticmethod + def show_tip( + widget: QWidget, pos: QPoint, text: str, timeout=-1, + textFormat=Qt.AutoText, wordWrap=None): + """Show a tooltip; used for invalid custom thresholds""" + propname = __name__ + "::show_tip_qlabel" + if timeout < 0: + timeout = widget.toolTipDuration() + if timeout < 0: + timeout = 5000 + 40 * max(0, len(text) - 100) + tip = widget.property(propname) + if not text and tip is None: + return -def show_tip( - widget: QWidget, pos: QPoint, text: str, timeout=-1, - textFormat=Qt.AutoText, wordWrap=None): - propname = __name__ + "::show_tip_qlabel" - if timeout < 0: - timeout = widget.toolTipDuration() - if timeout < 0: - timeout = 5000 + 40 * max(0, len(text) - 100) - tip = widget.property(propname) - if not text and tip is None: - return - - def hide(): - w = tip.parent() - w.setProperty(propname, None) - tip.timer.stop() - tip.close() - tip.deleteLater() - - if not isinstance(tip, QLabel): - tip = QLabel(objectName="tip-label", focusPolicy=Qt.NoFocus) - tip.setBackgroundRole(QPalette.ToolTipBase) - tip.setForegroundRole(QPalette.ToolTipText) - tip.setPalette(QToolTip.palette()) - tip.setFont(QApplication.font("QTipLabel")) - tip.setContentsMargins(2, 2, 2, 2) - tip.timer = QTimer(tip, singleShot=True, objectName="hide-timer") - tip.timer.timeout.connect(hide) - widget.setProperty(propname, tip) - tip.setParent(widget, Qt.ToolTip) - - tip.setText(text) - tip.setTextFormat(textFormat) - if wordWrap is None: - wordWrap = textFormat != Qt.PlainText - tip.setWordWrap(wordWrap) - - if not text: - hide() - else: - tip.timer.start(timeout) - tip.show() - tip.move(pos) + def hide(): + w = tip.parent() + w.setProperty(propname, None) + tip.timer.stop() + tip.close() + tip.deleteLater() + + if not isinstance(tip, QLabel): + tip = QLabel(objectName="tip-label", focusPolicy=Qt.NoFocus) + tip.setBackgroundRole(QPalette.ToolTipBase) + tip.setForegroundRole(QPalette.ToolTipText) + tip.setPalette(QToolTip.palette()) + tip.setFont(QApplication.font("QTipLabel")) + tip.setContentsMargins(2, 2, 2, 2) + tip.timer = QTimer(tip, singleShot=True, objectName="hide-timer") + tip.timer.timeout.connect(hide) + widget.setProperty(propname, tip) + tip.setParent(widget, Qt.ToolTip) + + tip.setText(text) + tip.setTextFormat(textFormat) + if wordWrap is None: + wordWrap = textFormat != Qt.PlainText + tip.setWordWrap(wordWrap) + + if not text: + hide() + else: + tip.timer.start(timeout) + tip.show() + tip.move(pos) class DiscretizeContextHandler(ContextHandler): - def match(self, context, data: Table): + def match(self, context, data: Table): # pylint: disable=arguments-differ if data is None: return self.NO_MATCH domain: Domain = data.domain @@ -377,12 +471,15 @@ def match(self, context, data: Table): # These are no longer used, but needed for loading and migrating old pickles. # We insert them into namespace instead of normally defining them, in order # to hide it from IDE's and avoid mistakenly using them. +# pylint: disable=wrong-import-position,wrong-import-order +from collections import namedtuple globals().update(dict( DState=namedtuple( "DState", - ["method", # discretization method - "points", # induced cut points - "disc_var"] # induced discretized variable + ["method", # discretization method + "points", # induced cut points + "disc_var"], + defaults=(None, None) # induced discretized variable ), Default=namedtuple("Default", ["method"]), Leave=namedtuple("Leave", []), @@ -436,7 +533,8 @@ def __init__(self): self.varview.select_default() def _create_var_list(self, box): - # If we don't elide, remove the `uniformItemSize` argument + """Create list view with variables""" + # If we decide to not elide, remove the `uniformItemSize` argument self.varview = ListViewSearch( selectionMode=QListView.ExtendedSelection, uniformItemSizes=True) self.varview.setModel( @@ -448,10 +546,11 @@ def _create_var_list(self, box): self._var_selection_changed) self.varview.default_view.selectionModel().selectionChanged.connect( self._default_selected) - self._set_default_data() + self._update_default_model() box.layout().addWidget(self.varview) def _create_buttons(self, box): + """Create radio buttons""" def intspin(): s = QSpinBox(self) s.setMinimum(2) @@ -503,9 +602,10 @@ def update(): p = edit.mapToGlobal(cr.bottomRight()) edit.setPalette(palette) if state != QValidator.Acceptable and edit.isVisible(): - show_tip(edit, p, edit.toolTip(), textFormat=Qt.RichText) + validator.show_tip(edit, p, edit.toolTip(), + textFormat=Qt.RichText) else: - show_tip(edit, p, "") + validator.show_tip(edit, p, "") return edit, edit.textChanged children = [] @@ -571,26 +671,43 @@ def arg_changed(): w.itemAt(0).widget().setFixedHeight(maxheight) button_box.layout().addStretch(1) - @Inputs.data - def set_data(self, data): - self.closeContext() - self.data = data - - self.var_hints = {DefaultKey: DefaultHint} - self.discretized_vars = {} + def _update_default_model(self): + """Update data in the model showing default settings""" + model = self.varview.default_view.model() + model.setData(model.index(0), self.var_hints[DefaultKey], Qt.UserRole) - if self.data is not None: - self.varview.model().set_domain(data.domain) - self.openContext(data) - self._update_points() + def _set_mdl_button(self): + """Disable MDL discretization for data with non-discrete class""" + mdl_button = self.button_group.button(Methods.MDL) + if self.data is None or self.data.domain.has_discrete_class: + mdl_button.setEnabled(True) else: - self.varview.model().set_domain(None) + if mdl_button.isChecked(): + self._check_button(Methods.Keep, True) + mdl_button.setEnabled(False) - self._set_default_data() - self._set_mdl_button() - self.commit.now() + def _check_button(self, method_id: Methods, checked: bool): + """Checks the given button""" + self.button_group.button(method_id).setChecked(checked) - def _get_values(self, controls: Tuple[str]): + def _uncheck_all_buttons(self): + """Uncheck all radio buttons""" + group = self.button_group + button = group.checkedButton() + if button is not None: + group.setExclusive(False) + button.setChecked(False) + group.setExclusive(True) + + def _set_radio_enabled(self, method_id: Methods, value: bool): + """Enable/disable radio button and related controls""" + self.button_group.button(method_id).setEnabled(value) + for control_name in Options[method_id].controls: + getattr(self, control_name).setEnabled(value) + + def _get_values(self, method_id: Methods) -> Tuple[Union[int, float, str]]: + """Return parameters from controls pertaining to the given method""" + controls = Options[method_id].controls values = [] for control_name in controls: control = getattr(self, control_name) @@ -602,8 +719,12 @@ def _get_values(self, controls: Tuple[str]): values.append(control.text()) return tuple(values) - def _set_values(self, controls: Tuple[str], - values: Tuple[Union[str, int, float]]): + def _set_values(self, method_id: Methods, + values: Tuple[Union[str, int, float]]): + """ + Set controls pertaining to the given method to parameters from hint + """ + controls = Options[method_id].controls for control_name, value in zip(controls, values): control = getattr(self, control_name) if isinstance(control, QSpinBox): @@ -613,22 +734,30 @@ def _set_values(self, controls: Tuple[str], else: control.setText(value) - def _set_mdl_button(self): - mdl_button = self.button_group.button(Methods.MDL) - if self.data is None or self.data.domain.has_discrete_class: - mdl_button.setEnabled(True) - else: - if mdl_button.isChecked(): - self._set_button(Methods.Keep, True) - mdl_button.setEnabled(False) + def varkeys_for_selection(self) -> List[KeyType]: + """ + Return list of KeyType's for selected variables (for indexing var_hints) - def varkeys_for_selection(self): + If 'Default settings' are selected, this returns DefaultKey + """ model = self.varview.model() - varkeys = [variable_key(model[i]) for i in self.selected_indices()] + varkeys = [variable_key(model[index.row()]) + for index in self.varview.selectionModel().selectedRows()] return varkeys or [DefaultKey] # default settings are selected - def update_hints(self, method_id): - args = self._get_values(Options[method_id].controls) + def update_hints(self, method_id: Methods): + """ + Callback for radio buttons and for controls regulating parameters + + This function: + - updates `var_hints` for all selected methods + - invalidates (removes) `discretized_vars` for affected variables + - calls _update_discretizations to compute and commit new discretization + - calls deferred commit + + Data for list view models is updated in _update_discretizations + """ + args = self._get_values(method_id) keys = self.varkeys_for_selection() if method_id == Methods.Default: for key in keys: @@ -644,18 +773,29 @@ def update_hints(self, method_id): del self.discretized_vars[key] if keys == [DefaultKey]: - self._set_default_data() - self._update_points() + self._update_default_model() + self._update_discretizations() + self.commit.deferred() - def _set_default_data(self): - model = self.varview.default_view.model() - model.setData(model.index(0), self.var_hints[DefaultKey], Qt.UserRole) + def _update_discretizations(self): + """ + Compute invalidated (missing) discretizations - def _update_points(self): + Also set data for list view models for all invalidated variables + """ if self.data is None: return - def induce_cuts(data, var, hint: VarHint): + def discretize(data: Table, var: ContinuousVariable, hint: VarHint) \ + -> Tuple[str, Optional[Variable]]: + """ + Discretize using method and data in the hint. + + Returns a description (list of points or error/warning) and a + - discrete variable + - same variable (if kept numeric) + - None (if removed or errored) + """ if isinstance(var, TimeVariable): if hint.method_id in (Methods.FixedWidth, Methods.Custom): return ": ", var @@ -671,29 +811,40 @@ def induce_cuts(data, var, hint: VarHint): return "", None # removed elif dvar is var: return "", var # no transformation - elif isinstance(dvar.compute_value, disc.Discretizer): - points = dvar.compute_value.points - if len(points) == 0: - return " ", None - return ": " + ", ".join(map(var.repr_val, points)), dvar - raise ValueError + thresholds = dvar.compute_value.points + if len(thresholds) == 0: + return " ", None + return ": " + ", ".join(map(var.repr_val, thresholds)), dvar default_hint = self.var_hints[DefaultKey] model = self.varview.model() for index, var in enumerate(model): key = variable_key(var) - if key not in self.discretized_vars: - var_hint = self.var_hints.get(key) - points, dvar = induce_cuts(self.data, var, var_hint or default_hint) - self.discretized_vars[key] = dvar - values = getattr(dvar, "values", ()) - model.setData(model.index(index), - DiscDesc(var_hint, points, values), - Qt.UserRole) - - self.commit.deferred() + if key in self.discretized_vars: + continue # still valid + var_hint = self.var_hints.get(key) + points, dvar = discretize(self.data, var, var_hint or default_hint) + self.discretized_vars[key] = dvar + values = getattr(dvar, "values", ()) + model.setData(model.index(index), + DiscDesc(var_hint, points, values), + Qt.UserRole) def _copy_to_manual(self): + """ + Callback for 'CC' button + + Sets selected variables' method to "Custom" and copies thresholds + to their VarHints. Variables that are not discretized (for any reason) + are skipped. + + Discretizations are invalidated and then updated + (`_update_discretizations`). + + If all selected variables have the same thresholds, it copies it to + the line edit. Otherwise it unchecks all radio buttons to keep the + interface consistent. + """ varkeys = self.varkeys_for_selection() texts = set() for key in varkeys: @@ -707,83 +858,90 @@ def _copy_to_manual(self): if len(texts) == 1: self.threshold_line.setText(texts.pop()) else: - self._uncheck_all_radios() - self._update_points() - - def _set_button(self, method_id, checked): - self.button_group.button(method_id).setChecked(checked) + self._uncheck_all_buttons() + self._update_discretizations() + self.commit.deferred() def _default_selected(self, selected): + """Callback for selecting 'Default setting'""" if not selected: + # Prevent infinite recursion (with _var_selection_changed) return self.varview.selectionModel().clearSelection() - self.set_method_state([DefaultKey]) - self.enable_radios([DefaultKey]) + self._update_interface() + + set_enabled = self._set_radio_enabled + set_enabled(Methods.Default, False) + set_enabled(Methods.FixedWidth, True) + set_enabled(Methods.FixedWidthTime, True) + set_enabled(Methods.Custom, True) def _var_selection_changed(self, selected): + """Callback for changed selection in listview with variables""" if not selected: + # Prevent infinite recursion (with _default_selected) return self.varview.default_view.selectionModel().clearSelection() - indices = self.selected_indices() - # set of all methods for the current selection - model = self.varview.model() - keys = [variable_key(model[i]) for i in indices] - self.set_method_state(keys) - self.enable_radios(keys) - - def enable_radios(self, keys): - def set_enabled(method_id, value): - self.button_group.button(method_id).setEnabled(value) - for control_name in Options[method_id].controls: - getattr(self, control_name).setEnabled(value) - - if keys == [DefaultKey]: - set_enabled(Methods.Default, False) - set_enabled(Methods.FixedWidth, True) - set_enabled(Methods.FixedWidthTime, True) - set_enabled(Methods.Custom, True) - else: - set_enabled(Methods.Default, True) - vars_ = [self.data.domain[name] for name, _ in keys] - no_time = not any(isinstance(var, TimeVariable) for var in vars_) - set_enabled(Methods.FixedWidth, no_time) - set_enabled(Methods.Custom, no_time) - set_enabled(Methods.FixedWidthTime, - all(isinstance(var, TimeVariable) for var in vars_)) - - def set_method_state(self, keys): + self._update_interface() + + set_enabled = self._set_radio_enabled + vars_ = [self.data.domain[name] + for name, _ in self.varkeys_for_selection()] + no_time = not any(isinstance(var, TimeVariable) for var in vars_) + all_time = all(isinstance(var, TimeVariable) for var in vars_) + set_enabled(Methods.Default, True) + set_enabled(Methods.FixedWidth, no_time) + set_enabled(Methods.Custom, no_time) + set_enabled(Methods.FixedWidthTime, all_time) + + def _update_interface(self): + """ + Update the user interface according to selection + + - If VarHints for all selected variables are the same, check the + corresponding radio button and fill the corresponding controls; + - otherwise, uncheck all radios. + """ + keys = self.varkeys_for_selection() mset = list(unique_everseen(map(self.var_hints.get, keys))) if len(mset) == 1: if mset == [None]: method_id, args = Methods.Default, () else: method_id, args = mset.pop() - method = Options[method_id] - self._set_button(method_id, True) - self._set_values(method.controls, args) - if method_id != Methods.Custom: - self.threshold_line.setText("") + self._check_button(method_id, True) + self._set_values(method_id, args) else: - self._uncheck_all_radios() + self._uncheck_all_buttons() - def _uncheck_all_radios(self): - group = self.button_group - button = group.checkedButton() - if button is not None: - group.setExclusive(False) - button.setChecked(False) - group.setExclusive(True) + @Inputs.data + def set_data(self, data: Optional[Table]): + self.closeContext() + self.data = data - def selected_indices(self): - rows = self.varview.selectionModel().selectedRows() - return [index.row() for index in rows] + self.var_hints = {DefaultKey: DefaultHint} + self.discretized_vars = {} - def discretized_domain(self): - def disc_var(var: ContinuousVariable) -> Optional[DiscreteVariable]: - return self.discretized_vars.get(variable_key(var), var) + if self.data is not None: + self.varview.model().set_domain(data.domain) + self.openContext(data) + self._update_discretizations() + else: + self.varview.model().set_domain(None) + + self._update_default_model() + self._set_mdl_button() + self.commit.now() + @gui.deferred + def commit(self): if self.data is None: - return None + self.Outputs.data.send(None) + return + + def disc_var(var: ContinuousVariable) \ + -> Union[DiscreteVariable, ContinuousVariable]: + return self.discretized_vars.get(variable_key(var), var) attributes = (disc_var(v) for v in self.data.domain.attributes) attributes = [v for v in attributes if v is not None] @@ -791,14 +949,8 @@ def disc_var(var: ContinuousVariable) -> Optional[DiscreteVariable]: class_vars = (disc_var(v) for v in self.data.domain.class_vars) class_vars = [v for v in class_vars if v is not None] - return Domain(attributes, class_vars, metas=self.data.domain.metas) - - @gui.deferred - def commit(self): - output = None - if self.data is not None: - domain = self.discretized_domain() - output = self.data.transform(domain) + domain = Domain(attributes, class_vars, metas=self.data.domain.metas) + output = self.data.transform(domain) self.Outputs.data.send(output) def send_report(self): diff --git a/Orange/widgets/data/tests/test_owdiscretize.py b/Orange/widgets/data/tests/test_owdiscretize.py index 0dd7dd83323..067c067d42b 100644 --- a/Orange/widgets/data/tests/test_owdiscretize.py +++ b/Orange/widgets/data/tests/test_owdiscretize.py @@ -7,17 +7,16 @@ from AnyQt.QtCore import QPoint from AnyQt.QtWidgets import QWidget, QApplication +from orangewidget.settings import Context + from Orange.data import Table, ContinuousVariable, TimeVariable from Orange.preprocess.discretize import TooManyIntervals -from Orange.widgets.data.owdiscretize import OWDiscretize, Default, EqualFreq, \ - Remove, Leave, Custom, IncreasingNumbersListValidator, MDL, \ - EqualWidth, DState, show_tip, VarHint, Methods, DefaultKey, \ - fixed_width_discretization, fixed_time_width_discretization, \ - custom_discretization, variable_key, DefaultHint -from Orange.widgets.tests.base import WidgetTest -from Orange.widgets.tests.base import GuiTest +from Orange.widgets.data.owdiscretize import OWDiscretize, \ + IncreasingNumbersListValidator, VarHint, Methods, DefaultKey, \ + _fixed_width_discretization, _fixed_time_width_discretization, \ + _custom_discretization, variable_key, DefaultHint +from Orange.widgets.tests.base import WidgetTest, GuiTest from Orange.widgets.utils.itemmodels import select_row -from orangewidget.settings import Context class TestOWDiscretize(WidgetTest): @@ -35,6 +34,7 @@ def test_empty_data(self): widget.commit.now() self.assertIsNotNone(self.get_output(widget.Outputs.data)) + """ def test_select_method(self): widget = self.widget data = Table("iris")[::5] @@ -99,7 +99,7 @@ def test_manual_cuts_edit(self): ledit.setText("") ledit.editingFinished.emit() self.assertEqual(widget.method_for_index(0), Custom(())) - +""" def test_report(self): widget = self.widget data = Table("iris")[::5] @@ -164,14 +164,19 @@ def test_all(self): self.assertTrue(w.button_group.button(Methods.MDL).isEnabled()) def test_migration_2_3(self): + # Obsolete, don't want to cause confusion by public import + # pylint: disable=import-outside-toplevel + from Orange.widgets.data.owdiscretize import \ + Default, EqualFreq, Leave, Custom, MDL, EqualWidth, DState context_values = { 'saved_var_states': - ({(2, 'age'): DState(method=Leave(), points=None, disc_var=None), - (2, 'rest SBP'): DState(method=EqualWidth(k=4), points=None, disc_var=None), - (2, 'cholesterol'): DState(method=EqualFreq(k=6), points=None, disc_var=None), - (4, 'max HR'): DState(method=Custom(points=(1.0, 2.0, 3.0)), points=None, disc_var=None), - (2, 'ST by exercise'): DState(method=MDL(), points=None, disc_var=None), - (2, 'major vessels colored'): DState(method=Default(method=EqualFreq(k=3)), points=None, disc_var=None)}, -2), + ({(2, 'age'): DState(method=Leave()), + (2, 'rest SBP'): DState(method=EqualWidth(k=4)), + (2, 'cholesterol'): DState(method=EqualFreq(k=6)), + (4, 'max HR'): DState(method=Custom(points=(1.0, 2.0, 3.0))), + (2, 'ST by exercise'): DState(method=MDL()), + (2, 'major vessels colored'): + DState(method=Default(method=EqualFreq(k=3)))}, -2), '__version__': 2} settings = {'autosend': True, 'controlAreaVisible': True, @@ -215,6 +220,7 @@ def test_validate(self): class TestUtils(GuiTest): def test_show_tip(self): w = QWidget() + show_tip = IncreasingNumbersListValidator.show_tip show_tip(w, QPoint(100, 100), "Ha Ha") app = QApplication.instance() windows = app.topLevelWidgets() @@ -229,7 +235,7 @@ def test_show_tip(self): self.assertFalse(label.isVisible()) def test_fixed_width_disc(self): - fw = partial(fixed_width_discretization, None, None) + fw = partial(_fixed_width_discretization, None, None) for arg in ("", "5.3.1", "abc"): self.assertIsInstance(fw(arg), str) @@ -245,7 +251,7 @@ def test_fixed_width_disc(self): self.assertIsInstance(fw("42"), str) def test_fixed_time_width_disc(self): - ftw = partial(fixed_time_width_discretization, None, None) + ftw = partial(_fixed_time_width_discretization, None, None) for arg in ("", "5.3.1", "5.3", "abc"): self.assertIsInstance(ftw(arg, 1), str) @@ -265,7 +271,7 @@ def test_fixed_time_width_disc(self): self.assertIsInstance(ftw("42", 3), str) def test_custom_discretization(self): - cd = partial(custom_discretization, None, None) + cd = partial(_custom_discretization, None, None) for arg in ("", "4 5", "2, 1, 5", "1, foo, 13"): self.assertIsInstance(cd(arg), str) @@ -283,4 +289,4 @@ def test_var_key(self): if __name__ == "__main__": - unittest.main() \ No newline at end of file + unittest.main() From 5efbf78bb9f6936c77eedf9ebe44c32841c48626 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 1 Apr 2022 11:24:59 +0200 Subject: [PATCH 3/9] Discretize: Replace context settings with schema-only non-context --- Orange/widgets/data/owdiscretize.py | 72 +++++++------------ .../widgets/data/tests/test_owdiscretize.py | 12 ++-- 2 files changed, 31 insertions(+), 53 deletions(-) diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 1d32a815734..8bc59de2a82 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -12,7 +12,7 @@ QLineEdit, QToolTip, QLabel, QApplication, QSpinBox, QSizePolicy, QRadioButton, QComboBox) -from orangewidget.settings import ContextHandler, Setting, ContextSetting +from orangewidget.settings import Setting from orangewidget.utils import listview from Orange.data import ( @@ -97,6 +97,14 @@ def _fixed_time_width_discretization( return TOO_MANY_INTERVALS +def _mdl_discretization( + data: Table, + var: Union[ContinuousVariable, str, int]) -> Union[DiscreteVariable, str]: + if not data.domain.has_discrete_class: + return "no discrete class" + return disc.EntropyMDL()(data, var) + + def _custom_discretization( _, var: Union[ContinuousVariable, str, int], @@ -161,7 +169,7 @@ class MethodDesc(NamedTuple): "Entropy vs. MDL", "entropy", "Split values until MDL exceeds the entropy (Fayyad-Irani)\n" "(requires discrete class variable)", - disc.EntropyMDL(), + _mdl_discretization, ()), MethodDesc(Methods.EqualFreq, "Equal frequency, intervals: ", "equal freq, k={}", @@ -448,26 +456,6 @@ def hide(): tip.move(pos) -class DiscretizeContextHandler(ContextHandler): - def match(self, context, data: Table): # pylint: disable=arguments-differ - if data is None: - return self.NO_MATCH - domain: Domain = data.domain - types = (ContinuousVariable, TimeVariable) - var_hints = context.values.get("var_hints") - if var_hints is None: # sanity check - return self.NO_MATCH - for key, hint in var_hints.items(): - if hint.method_id == Methods.MDL and not domain.has_discrete_class: - return self.NO_MATCH - if key is DefaultKey: - continue - name, tpe = key - if name not in domain or not isinstance(domain[name], types[tpe]): - return self.NO_MATCH - return self.PERFECT_MATCH - - # These are no longer used, but needed for loading and migrating old pickles. # We insert them into namespace instead of normally defining them, in order # to hide it from IDE's and avoid mistakenly using them. @@ -506,12 +494,12 @@ class Inputs: class Outputs: data = Output("Data", Table, doc="Table with categorical features") - settingsHandler = DiscretizeContextHandler() settings_version = 3 #: Default setting (key DefaultKey) and specific settings for variables; # if variable is not in the dict, it uses default - var_hints: Dict[KeyType, VarHint] = ContextSetting({DefaultKey: DefaultHint}) + var_hints: Dict[KeyType, VarHint] = Setting( + {DefaultKey: DefaultHint}, schema_only=True) autosend = Setting(True) want_main_area = False @@ -904,31 +892,23 @@ def _update_interface(self): """ keys = self.varkeys_for_selection() mset = list(unique_everseen(map(self.var_hints.get, keys))) - if len(mset) == 1: - if mset == [None]: - method_id, args = Methods.Default, () - else: - method_id, args = mset.pop() - self._check_button(method_id, True) - self._set_values(method_id, args) - else: + if len(mset) != 1: self._uncheck_all_buttons() + return + + if mset == [None]: + method_id, args = Methods.Default, () + else: + method_id, args = mset.pop() + self._check_button(method_id, True) + self._set_values(method_id, args) @Inputs.data def set_data(self, data: Optional[Table]): - self.closeContext() - self.data = data - - self.var_hints = {DefaultKey: DefaultHint} self.discretized_vars = {} - - if self.data is not None: - self.varview.model().set_domain(data.domain) - self.openContext(data) - self._update_discretizations() - else: - self.varview.model().set_domain(None) - + self.data = data + self.varview.model().set_domain(None if data is None else data.domain) + self._update_discretizations() self._update_default_model() self._set_mdl_button() self.commit.now() @@ -989,12 +969,12 @@ def migrate_settings(cls, settings, version): else: args = () default_hint = VarHint(method_id, args) + var_hints = {DefaultKey: default_hint} for context in settings.get("context_settings", []): values = context.values if "saved_var_states" not in values: continue var_states, _ = values.pop("saved_var_states") - var_hints = {DefaultKey: default_hint} for (tpe, name), dstate in var_states.items(): key = (name, tpe == 4) # time variable == 4 method = dstate.method @@ -1006,7 +986,7 @@ def migrate_settings(cls, settings, version): else: args = tuple(method) var_hints[key] = VarHint(getattr(Methods, method_name), args) - values["var_hints"] = var_hints + settings["var_hints"] = var_hints if __name__ == "__main__": # pragma: no cover diff --git a/Orange/widgets/data/tests/test_owdiscretize.py b/Orange/widgets/data/tests/test_owdiscretize.py index 067c067d42b..29077b45fd6 100644 --- a/Orange/widgets/data/tests/test_owdiscretize.py +++ b/Orange/widgets/data/tests/test_owdiscretize.py @@ -111,7 +111,7 @@ def test_all(self): w = self.create_widget( OWDiscretize, - dict(context_settings=[Context(values={"var_hints": + {"var_hints": {None: VarHint(Methods.EqualFreq, (3,)), ('alpha 0', False): VarHint(Methods.Keep, ()), ('alpha 7', False): VarHint(Methods.Remove, ()), @@ -120,7 +120,8 @@ def test_all(self): ('alpha 28', False): VarHint(Methods.EqualFreq, (4, )), ('alpha 35', False): VarHint(Methods.MDL, ()), ('alpha 42', False): VarHint(Methods.Custom, ("0, 0.125", )), - ('alpha 49', False): VarHint(Methods.MDL, ())}})])) + ('alpha 49', False): VarHint(Methods.MDL, ())}, + "__version__": 3}) self.send_signal(w.Inputs.data, data) @@ -145,9 +146,7 @@ def test_all(self): self.send_signal(w.Inputs.data, None) self.assertIsNone(self.get_output(w.Outputs.data)) self.assertIsNone(w.data) - self.assertEqual(list(w.var_hints), [DefaultKey]) self.assertEqual(w.discretized_vars, {}) - self.assertEqual(w.varview.default_view.model().hint, DefaultHint) self.assertEqual(len(w.varview.model()), 0) self.send_signal(w.Inputs.data, data) @@ -189,10 +188,9 @@ def test_migration_2_3(self): self.assertNotIn("default_method_name", settings) self.assertNotIn("default_k", settings) self.assertNotIn("default_cutpoints", settings) - values = settings["context_settings"][0].values - self.assertNotIn("saved_var_states", values) + self.assertNotIn("context_settings", settings) self.assertEqual( - values["var_hints"], + settings["var_hints"], {None: VarHint(Methods.EqualFreq, (3,)), ('ST by exercise', False): VarHint(Methods.MDL, ()), ('age', False): VarHint(Methods.Keep, ()), From 23f0cb5a5e7875629c763ba977ba9caf19b5ce88 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 1 Apr 2022 13:24:07 +0200 Subject: [PATCH 4/9] discretize: Use get_column_view instead of new table --- Orange/preprocess/discretize.py | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/Orange/preprocess/discretize.py b/Orange/preprocess/discretize.py index 83717c3adfe..86e3bbaef87 100644 --- a/Orange/preprocess/discretize.py +++ b/Orange/preprocess/discretize.py @@ -8,7 +8,7 @@ import numpy as np import scipy.sparse as sp -from Orange.data import DiscreteVariable, Domain, TimeVariable +from Orange.data import DiscreteVariable, Domain, TimeVariable, Table from Orange.data.sql.table import SqlTable from Orange.statistics import distribution, contingency, util as ut from Orange.statistics.basic_stats import BasicStats @@ -167,7 +167,7 @@ def __init__(self, n=4): self.n = n # noinspection PyProtectedMember - def __call__(self, data, attribute, fixed=None): + def __call__(self, data: Table, attribute, fixed=None): if fixed: min, max = fixed[attribute.name] points = self._split_eq_width(min, max) @@ -176,8 +176,7 @@ def __call__(self, data, attribute, fixed=None): stats = BasicStats(data, attribute) points = self._split_eq_width(stats.min, stats.max) else: - values = data[:, attribute] - values = values.X if values.X.size else values.Y + values, _ = data.get_column_view(attribute) if values.size: min, max = ut.nanmin(values), ut.nanmax(values) points = self._split_eq_width(min, max) @@ -203,9 +202,8 @@ def __init__(self, width, digits=None): self.width = width self.digits = digits - def __call__(self, data, attribute): - values = data[:, attribute] - values = values.X if values.X.size else values.Y + def __call__(self, data: Table, attribute): + values, _ = data.get_column_view(attribute) points = [] if values.size: mn, mx = ut.nanmin(values), ut.nanmax(values) @@ -227,11 +225,10 @@ def __init__(self, width, unit): self.width = width self.unit = unit - def __call__(self, data, attribute): + def __call__(self, data: Table, attribute): fmt = ["%Y", "%y %b", "%y %b %d", "%y %b %d %H:%M", "%y %b %d %H:%M", "%H:%M:%S"][self.unit] - values = data[:, attribute] - values = values.X if values.X.size else values.Y + values, _ = data.get_column_view(attribute) times = [] if values.size: mn, mx = ut.nanmin(values), ut.nanmax(values) @@ -294,10 +291,9 @@ class Binning(Discretization): def __init__(self, n=4): self.n = n - def __call__(self, data, attribute): + def __call__(self, data: Table, attribute): attribute = data.domain[attribute] - values = data[:, attribute] - values = values.X if values.X.size else values.Y + values, _ = data.get_column_view(attribute) if not values.size: return self._create_binned_var(None, attribute) From 8e0a18ff1bb3be6b1bedc3696aff0b43fb675b9d Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 1 Apr 2022 13:25:06 +0200 Subject: [PATCH 5/9] OWDiscretize: More tidying up --- Orange/preprocess/discretize.py | 23 +- Orange/preprocess/tests/test_discretize.py | 6 +- Orange/widgets/data/owdiscretize.py | 150 +++-- .../widgets/data/tests/test_owdiscretize.py | 555 +++++++++++++++--- 4 files changed, 576 insertions(+), 158 deletions(-) diff --git a/Orange/preprocess/discretize.py b/Orange/preprocess/discretize.py index 86e3bbaef87..65ed508da13 100644 --- a/Orange/preprocess/discretize.py +++ b/Orange/preprocess/discretize.py @@ -169,8 +169,8 @@ def __init__(self, n=4): # noinspection PyProtectedMember def __call__(self, data: Table, attribute, fixed=None): if fixed: - min, max = fixed[attribute.name] - points = self._split_eq_width(min, max) + mn, mx = fixed[attribute.name] + points = self._split_eq_width(mn, mx) else: if type(data) == SqlTable: stats = BasicStats(data, attribute) @@ -178,18 +178,18 @@ def __call__(self, data: Table, attribute, fixed=None): else: values, _ = data.get_column_view(attribute) if values.size: - min, max = ut.nanmin(values), ut.nanmax(values) - points = self._split_eq_width(min, max) + mn, mx = ut.nanmin(values), ut.nanmax(values) + points = self._split_eq_width(mn, mx) else: points = [] return Discretizer.create_discretized_var( data.domain[attribute], points) - def _split_eq_width(self, min, max): - if np.isnan(min) or np.isnan(max) or min == max: + def _split_eq_width(self, mn, mx): + if np.isnan(mn) or np.isnan(mx) or mn == mx: return [] - dif = (max - min) / self.n - return [min + i * dif for i in range(1, self.n)] + dif = (mx - mn) / self.n + return [mn + i * dif for i in range(1, self.n)] class TooManyIntervals(ValueError): @@ -255,7 +255,8 @@ def no_common(a, b): if common + i == 2: i -= 1 return b[i:] - return b # can't come here (unless a == b?!) + # can't come here (unless a == b?!) + return b # pragma: no cover if not labels: @@ -294,6 +295,7 @@ def __init__(self, n=4): def __call__(self, data: Table, attribute): attribute = data.domain[attribute] values, _ = data.get_column_view(attribute) + values = values.astype(float) if not values.size: return self._create_binned_var(None, attribute) @@ -319,6 +321,9 @@ def _create_binned_var(self, binnings, variable): -len(binning.short_labels)), default=binnings[-1]) + if len(binning.thresholds) == 2: + return Discretizer.create_discretized_var(variable, []) + blabels = binning.labels[1:-1] labels = [f"< {blabels[0]}"] + [ f"{lab1} - {lab2}" for lab1, lab2 in zip(blabels, blabels[1:]) diff --git a/Orange/preprocess/tests/test_discretize.py b/Orange/preprocess/tests/test_discretize.py index b18cf716901..6ae4a6f4ac6 100644 --- a/Orange/preprocess/tests/test_discretize.py +++ b/Orange/preprocess/tests/test_discretize.py @@ -268,6 +268,8 @@ def test_discretization(self): self.assertEqual(dvar.values, ('< 23:59:59', "23:59:59 - 00:00:00", "00:00:00 - 00:00:01", '≥ 00:00:01')) + self.assertRaises(TooManyIntervals, FixedTimeWidth(0.0001, 5), data, 0) + class TestBinningDiscretizer(unittest.TestCase): def test_no_data(self): @@ -350,12 +352,12 @@ def tr1(s): s = s.replace(localname, engname) return s - def tr(ss): + def tr2(ss): return list(map(tr1, ss)) def testbin(start, end): bins = _time_binnings(create(*start), create(*end), 3, 51) - return [(bin.width_label, tr(bin.short_labels), + return [(bin.width_label, tr2(bin.short_labels), list(bin.thresholds)) for bin in reversed(bins)] diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 8bc59de2a82..625582096fc 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -16,7 +16,7 @@ from orangewidget.utils import listview from Orange.data import ( - ContinuousVariable, DiscreteVariable, TimeVariable, Domain, Table, Variable) + Variable, ContinuousVariable, DiscreteVariable, TimeVariable, Domain, Table) import Orange.preprocess.discretize as disc from Orange.widgets import widget, gui from Orange.widgets.utils import unique_everseen @@ -64,6 +64,7 @@ def _fixed_width_discretization( return TOO_MANY_INTERVALS +# pylint: disable=invalid-name def _fixed_time_width_discretization( data: Table, var: Union[TimeVariable, str, int], @@ -307,12 +308,15 @@ def format_desc(hint: VarHint) -> str: desc = Options[hint.method_id].short_desc if hint.method_id == Methods.FixedWidthTime: width, unit = hint.args + unit = time_units[unit] try: width = int(width) except ValueError: - pass + unit += "(s)" else: - return desc.format(width, time_units[unit] + "s" * (int(width) != 1)) + if width != 1: + unit += "s" + return desc.format(width, unit) return desc.format(*hint.args) @@ -374,12 +378,10 @@ def data(self, _, role=Qt.DisplayRole): return "Default setting for variables without specific setings" return None - def setData(self, index, value, role): + def setData(self, index, value, role=Qt.DisplayRole): if role == Qt.UserRole: self.hint = value self.dataChanged.emit(index, index) - else: - super().set_data(index, value, role) class IncreasingNumbersListValidator(QValidator): @@ -512,6 +514,12 @@ def __init__(self): #: Cached discretized variables self.discretized_vars: Dict[KeyType, DiscreteVariable] = {} + # Indicates that buttons, spins, edit and combos are being changed + # programmatically (when interface is changed due to selection change), + # so this should not trigger update of hints and invalidation of + # discretization in `self.discretized_vars`. + self.__interface_update = False + box = gui.hBox(self.controlArea, True, spacing=8) self._create_var_list(box) self._create_buttons(box) @@ -622,6 +630,7 @@ def arg_changed(): button_box = gui.vBox(box) button_box.layout().setSpacing(0) + button_box.setSizePolicy(QSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)) self.button_group = QButtonGroup(self) self.button_group.idClicked.connect(self.update_hints) @@ -689,6 +698,8 @@ def _uncheck_all_buttons(self): def _set_radio_enabled(self, method_id: Methods, value: bool): """Enable/disable radio button and related controls""" + if self.button_group.button(method_id).isChecked() and not value: + self._uncheck_all_buttons() self.button_group.button(method_id).setEnabled(value) for control_name in Options[method_id].controls: getattr(self, control_name).setEnabled(value) @@ -745,6 +756,10 @@ def update_hints(self, method_id: Methods): Data for list view models is updated in _update_discretizations """ + if self.__interface_update: + return + + method_id = Methods(method_id) args = self._get_values(method_id) keys = self.varkeys_for_selection() if method_id == Methods.Default: @@ -774,36 +789,6 @@ def _update_discretizations(self): if self.data is None: return - def discretize(data: Table, var: ContinuousVariable, hint: VarHint) \ - -> Tuple[str, Optional[Variable]]: - """ - Discretize using method and data in the hint. - - Returns a description (list of points or error/warning) and a - - discrete variable - - same variable (if kept numeric) - - None (if removed or errored) - """ - if isinstance(var, TimeVariable): - if hint.method_id in (Methods.FixedWidth, Methods.Custom): - return ": ", var - else: - if hint.method_id == Methods.FixedWidthTime: - return ": ", var - - function = Options[hint.method_id].function - dvar = function(data, var, *hint.args) - if isinstance(dvar, str): - return f" <{dvar}>", None # error - if dvar is None: - return "", None # removed - elif dvar is var: - return "", var # no transformation - thresholds = dvar.compute_value.points - if len(thresholds) == 0: - return " ", None - return ": " + ", ".join(map(var.repr_val, thresholds)), dvar - default_hint = self.var_hints[DefaultKey] model = self.varview.model() for index, var in enumerate(model): @@ -811,13 +796,43 @@ def discretize(data: Table, var: ContinuousVariable, hint: VarHint) \ if key in self.discretized_vars: continue # still valid var_hint = self.var_hints.get(key) - points, dvar = discretize(self.data, var, var_hint or default_hint) + points, dvar = self._discretize_var(var, var_hint or default_hint) self.discretized_vars[key] = dvar values = getattr(dvar, "values", ()) model.setData(model.index(index), DiscDesc(var_hint, points, values), Qt.UserRole) + def _discretize_var(self, var: ContinuousVariable, hint: VarHint) \ + -> Tuple[str, Optional[Variable]]: + """ + Discretize using method and data in the hint. + + Returns a description (list of points or error/warning) and a + - discrete variable + - same variable (if kept numeric) + - None (if removed or errored) + """ + if isinstance(var, TimeVariable): + if hint.method_id in (Methods.FixedWidth, Methods.Custom): + return ": ", var + else: + if hint.method_id == Methods.FixedWidthTime: + return ": ", var + + function = Options[hint.method_id].function + dvar = function(self.data, var, *hint.args) + if isinstance(dvar, str): + return f" <{dvar}>", None # error + if dvar is None: + return "", None # removed + elif dvar is var: + return "", var # no transformation + thresholds = dvar.compute_value.points + if len(thresholds) == 0: + return " ", None + return ": " + ", ".join(map(var.repr_val, thresholds)), dvar + def _copy_to_manual(self): """ Callback for 'CC' button @@ -843,10 +858,14 @@ def _copy_to_manual(self): texts.add(text) self.var_hints[key] = VarHint(Methods.Custom, (text, )) del self.discretized_vars[key] - if len(texts) == 1: - self.threshold_line.setText(texts.pop()) - else: - self._uncheck_all_buttons() + try: + self.__interface_update = True + if len(texts) == 1: + self.threshold_line.setText(texts.pop()) + else: + self._uncheck_all_buttons() + finally: + self.__interface_update = False self._update_discretizations() self.commit.deferred() @@ -864,8 +883,9 @@ def _default_selected(self, selected): set_enabled(Methods.FixedWidthTime, True) set_enabled(Methods.Custom, True) - def _var_selection_changed(self, selected): + def _var_selection_changed(self, _): """Callback for changed selection in listview with variables""" + selected = self.varview.selectionModel().selectedIndexes() if not selected: # Prevent infinite recursion (with _default_selected) return @@ -890,18 +910,25 @@ def _update_interface(self): corresponding radio button and fill the corresponding controls; - otherwise, uncheck all radios. """ - keys = self.varkeys_for_selection() - mset = list(unique_everseen(map(self.var_hints.get, keys))) - if len(mset) != 1: - self._uncheck_all_buttons() + if self.__interface_update: return - if mset == [None]: - method_id, args = Methods.Default, () - else: - method_id, args = mset.pop() - self._check_button(method_id, True) - self._set_values(method_id, args) + try: + self.__interface_update = True + keys = self.varkeys_for_selection() + mset = list(unique_everseen(map(self.var_hints.get, keys))) + if len(mset) != 1: + self._uncheck_all_buttons() + return + + if mset == [None]: + method_id, args = Methods.Default, () + else: + method_id, args = mset.pop() + self._check_button(method_id, True) + self._set_values(method_id, args) + finally: + self.__interface_update = False @Inputs.data def set_data(self, data: Optional[Table]): @@ -919,17 +946,14 @@ def commit(self): self.Outputs.data.send(None) return - def disc_var(var: ContinuousVariable) \ - -> Union[DiscreteVariable, ContinuousVariable]: - return self.discretized_vars.get(variable_key(var), var) - - attributes = (disc_var(v) for v in self.data.domain.attributes) - attributes = [v for v in attributes if v is not None] - - class_vars = (disc_var(v) for v in self.data.domain.class_vars) - class_vars = [v for v in class_vars if v is not None] + def part(variables: List[Variable]) -> List[Variable]: + return [dvar + for dvar in (self.discretized_vars.get(variable_key(v), v) + for v in variables) + if dvar] - domain = Domain(attributes, class_vars, metas=self.data.domain.metas) + d = self.data.domain + domain = Domain(part(d.attributes), part(d.class_vars), part(d.metas)) output = self.data.transform(domain) self.Outputs.data.send(output) @@ -970,7 +994,7 @@ def migrate_settings(cls, settings, version): args = () default_hint = VarHint(method_id, args) var_hints = {DefaultKey: default_hint} - for context in settings.get("context_settings", []): + for context in settings.pop("context_settings", []): values = context.values if "saved_var_states" not in values: continue diff --git a/Orange/widgets/data/tests/test_owdiscretize.py b/Orange/widgets/data/tests/test_owdiscretize.py index 29077b45fd6..f69cbd48537 100644 --- a/Orange/widgets/data/tests/test_owdiscretize.py +++ b/Orange/widgets/data/tests/test_owdiscretize.py @@ -2,28 +2,52 @@ # pylint: disable=missing-docstring,unsubscriptable-object,protected-access import unittest from functools import partial -from unittest.mock import patch +from unittest.mock import patch, Mock -from AnyQt.QtCore import QPoint -from AnyQt.QtWidgets import QWidget, QApplication +import numpy as np + +from AnyQt.QtCore import QPoint, Qt, QModelIndex +from AnyQt.QtWidgets import QWidget, QApplication, QStyleOptionViewItem +from AnyQt.QtGui import QIcon from orangewidget.settings import Context -from Orange.data import Table, ContinuousVariable, TimeVariable +from Orange.data import Table, ContinuousVariable, TimeVariable, Domain from Orange.preprocess.discretize import TooManyIntervals from Orange.widgets.data.owdiscretize import OWDiscretize, \ IncreasingNumbersListValidator, VarHint, Methods, DefaultKey, \ _fixed_width_discretization, _fixed_time_width_discretization, \ - _custom_discretization, variable_key, DefaultHint + _custom_discretization, variable_key, Options, DefaultHint, \ + _mdl_discretization, ListViewSearch, format_desc, DefaultDiscModel from Orange.widgets.tests.base import WidgetTest, GuiTest -from Orange.widgets.utils.itemmodels import select_row - - -class TestOWDiscretize(WidgetTest): +from Orange.widgets.utils.itemmodels import select_rows + + +class DataMixin: + def prepare_data(self): + self.domain = Domain([ContinuousVariable("x"), + ContinuousVariable("y"), + ContinuousVariable("z"), + TimeVariable("t"), + TimeVariable("u")]) + self.data = Table.from_numpy(self.domain, np.arange(20).reshape(4, 5)) + self.var_hints = { + DefaultKey: VarHint(Methods.Keep, ()), + ("x", False): VarHint(Methods.EqualFreq, (3, )), + ("y", False): VarHint(Methods.Keep, ()), + ("z", False): VarHint(Methods.Remove, ()), + ("t", True): VarHint(Methods.Binning, (2, )) + } + # Copy the following line to tests, for reference: + # Def: Keep, x: EqFreq 3, y: Keep, z: Remove, t (time): Bin 2, u (time): + +class TestOWDiscretize(WidgetTest, DataMixin): def setUp(self): super().setUp() + self.prepare_data() self.widget = self.create_widget(OWDiscretize) + def test_empty_data(self): data = Table("iris") widget = self.widget @@ -34,77 +58,25 @@ def test_empty_data(self): widget.commit.now() self.assertIsNotNone(self.get_output(widget.Outputs.data)) - """ - def test_select_method(self): - widget = self.widget - data = Table("iris")[::5] - self.send_signal(self.widget.Inputs.data, data) - - model = widget.varmodel - view = widget.varview - defbg = widget.default_button_group - varbg = widget.variable_button_group - self.assertSequenceEqual(list(model), data.domain.attributes) - defbg.button(OWDiscretize.EqualFreq).click() - self.assertEqual(widget.default_method, OWDiscretize.EqualFreq) - self.assertTrue( - all(isinstance(m, Default) and isinstance(m.method, EqualFreq) - for m in map(widget.method_for_index, - range(len(data.domain.attributes))))) - - # change method for first variable - select_row(view, 0) - varbg.button(OWDiscretize.Remove).click() - met = widget.method_for_index(0) - self.assertIsInstance(met, Remove) - - # select a second var - selmodel = view.selectionModel() - selmodel.select(model.index(2), selmodel.Select) - # the current checked button must unset - self.assertEqual(varbg.checkedId(), -1) - - varbg.button(OWDiscretize.Leave).click() - self.assertIsInstance(widget.method_for_index(0), Leave) - self.assertIsInstance(widget.method_for_index(2), Leave) - # reset both back to default - varbg.button(OWDiscretize.Default).click() - self.assertIsInstance(widget.method_for_index(0), Default) - self.assertIsInstance(widget.method_for_index(2), Default) - - def test_manual_cuts_edit(self): - widget = self.widget - data = Table("iris")[::5] - self.send_signal(self.widget.Inputs.data, data) - view = widget.varview - varbg = widget.variable_button_group - widget.set_default_method(OWDiscretize.Custom) - widget.default_cutpoints = (0, 2, 4) - ledit = widget.manual_cuts_edit - self.assertEqual(ledit.text(), "0, 2, 4") - ledit.setText("3, 4, 5") - ledit.editingFinished.emit() - self.assertEqual(widget.default_cutpoints, (3, 4, 5)) - self.assertEqual(widget._current_default_method(), Custom((3, 4, 5))) - self.assertTrue( - all(widget.method_for_index(i) == Default(Custom((3, 4, 5))) - for i in range(len(data.domain.attributes))) - ) - select_row(view, 0) - varbg.button(OWDiscretize.Custom).click() - ledit = widget.manual_cuts_specific - ledit.setText("1, 2, 3") - ledit.editingFinished.emit() - self.assertEqual(widget.method_for_index(0), Custom((1, 2, 3))) - ledit.setText("") - ledit.editingFinished.emit() - self.assertEqual(widget.method_for_index(0), Custom(())) -""" def test_report(self): - widget = self.widget - data = Table("iris")[::5] - self.send_signal(widget.Inputs.data, data) - widget.send_report() + data = Table("brown-selected") + + w = self.create_widget( + OWDiscretize, + {"var_hints": + {None: VarHint(Methods.EqualFreq, (3,)), + ('alpha 0', False): VarHint(Methods.Keep, ()), + ('alpha 7', False): VarHint(Methods.Remove, ()), + ('alpha 14', False): VarHint(Methods.Binning, (2, )), + ('alpha 21', False): VarHint(Methods.FixedWidth, ("0.05", )), + ('alpha 28', False): VarHint(Methods.EqualFreq, (4, )), + ('alpha 35', False): VarHint(Methods.MDL, ()), + ('alpha 42', False): VarHint(Methods.Custom, ("0, 0.125", )), + ('alpha 49', False): VarHint(Methods.MDL, ())}, + "__version__": 3}) + self.send_signal(w.Inputs.data, data) + + self.widget.send_report() def test_all(self): data = Table("brown-selected") @@ -162,6 +134,297 @@ def test_all(self): self.send_signal(w.Inputs.data, data) self.assertTrue(w.button_group.button(Methods.MDL).isEnabled()) + def test_get_values(self): + w = self.widget + + w.binning_spin.setValue(5) + w.width_line.setText("6") + w.width_time_line.setText("7") + w.width_time_unit.setCurrentIndex(1) + w.freq_spin.setValue(8) + w.width_spin.setValue(9) + w.threshold_line.setText("1, 2, 3, 4, 5") + + self.assertEqual(w._get_values(Methods.Keep), ()) + self.assertEqual(w._get_values(Methods.Remove), ()) + self.assertEqual(w._get_values(Methods.Binning), (5, )) + self.assertEqual(w._get_values(Methods.FixedWidth), ("6", )) + self.assertEqual(w._get_values(Methods.FixedWidthTime), ("7", 1)) + self.assertEqual(w._get_values(Methods.EqualFreq), (8, )) + self.assertEqual(w._get_values(Methods.EqualWidth), (9, )) + self.assertEqual(w._get_values(Methods.MDL), ()) + self.assertEqual(w._get_values(Methods.Custom), ("1, 2, 3, 4, 5", )) + + def test_set_values(self): + w = self.widget + + w._set_values(Methods.Keep, ()) + w._set_values(Methods.Remove, ()) + w._set_values(Methods.Binning, (5,)) + w._set_values(Methods.FixedWidth, ("6",)) + w._set_values(Methods.FixedWidthTime, ("7", 1)) + w._set_values(Methods.EqualFreq, (8,)) + w._set_values(Methods.EqualWidth, (9,)) + w._set_values(Methods.MDL, ()) + w._set_values(Methods.Custom, ("1, 2, 3, 4, 5",)) + + self.assertEqual(w.binning_spin.value(), 5) + self.assertEqual(w.width_line.text(), "6") + self.assertEqual(w.width_time_line.text(), "7") + self.assertEqual(w.width_time_unit.currentIndex(), 1) + self.assertEqual(w.freq_spin.value(), 8) + self.assertEqual(w.width_spin.value(), 9) + self.assertEqual(w.threshold_line.text(), "1, 2, 3, 4, 5") + + def test_varkeys_for_selection(self): + w = self.widget + self.send_signal(w.Inputs.data, self.data) + select_rows(w.varview, (0, 4)) + self.assertEqual(w.varkeys_for_selection(), [("x", False), ("u", True)]) + + def test_change_selection_update_interface(self): + w = self.widget + self.send_signal(w.Inputs.data, self.data) + w.var_hints = { + DefaultKey: DefaultHint, + ("x", False): VarHint(Methods.FixedWidth, ("10", )), + ("y", False): VarHint(Methods.FixedWidth, ("10", )), + ("z", False): VarHint(Methods.FixedWidth, ("5", )), + ("t", False): VarHint(Methods.Binning, (5, )) + } + + select_rows(w.varview, (0, 1)) + self.assertTrue(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertFalse(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + self.assertEqual(w.width_line.text(), "10") + + select_rows(w.varview, (1, 2)) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertFalse(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + + select_rows(w.varview, (2, 4)) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertFalse(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertFalse(w.button_group.button(Methods.Custom).isEnabled()) + + select_rows(w.varview, (3, 4)) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertTrue(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertFalse(w.button_group.button(Methods.Custom).isEnabled()) + + select_rows(w.varview.default_view, (0, )) + self.assertEqual(len(w.varview.selectionModel().selectedIndexes()), 0) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertTrue(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + self.assertFalse(w.button_group.button(Methods.Default).isEnabled()) + w._check_button(Methods.FixedWidth, True) + self.assertTrue(w.button_group.button(Methods.FixedWidth).isChecked()) + + select_rows(w.varview, (3, )) + self.assertEqual(len(w.varview.default_view.selectionModel().selectedIndexes()), 0) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) + self.assertFalse(w.button_group.button(Methods.FixedWidth).isEnabled()) + self.assertTrue(w.button_group.button(Methods.FixedWidthTime).isEnabled()) + self.assertFalse(w.button_group.button(Methods.Custom).isEnabled()) + self.assertTrue(w.button_group.button(Methods.Default).isEnabled()) + + def test_update_hints(self): + w = self.widget + update_disc = w._update_discretizations + w._update_discretizations = Mock() + w.width_line.setText("10") + self.send_signal(w.Inputs.data, self.data) + w.var_hints = { + DefaultKey: DefaultHint, + ("x", False): VarHint(Methods.EqualFreq, (3, )), + ("y", False): VarHint(Methods.EqualFreq, (3, )), + ("z", False): VarHint(Methods.EqualFreq, (4, )), + ("t", True): VarHint(Methods.Binning, (5, )) + } + update_disc() + self.assertEqual(len(w.discretized_vars), 5) + + select_rows(w.varview, (0, )) + w.button_group.button(Methods.Default).click() + self.assertNotIn(("x", False), w.var_hints) + # Check that "x" is invalidated + self.assertEqual(len(w.discretized_vars), 4) + self.assertNotIn(("x", False), w.discretized_vars) + update_disc() + self.assertEqual(len(w.discretized_vars), 5) + self.assertIn(("x", False), w.discretized_vars) + + select_rows(w.varview, (0, 1)) + w.button_group.button(Methods.FixedWidth).click() + self.assertEqual(w.var_hints[("x", False)], + VarHint(Methods.FixedWidth, ("10", ))) + self.assertEqual(w.var_hints[("y", False)], + VarHint(Methods.FixedWidth, ("10", ))) + # Check that "x" and "y" are invalidated + self.assertEqual(len(w.discretized_vars), 3) + self.assertNotIn(("x", False), w.discretized_vars) + self.assertNotIn(("y", False), w.discretized_vars) + update_disc() + self.assertEqual(len(w.discretized_vars), 5) + self.assertIn(("x", False), w.discretized_vars) + self.assertIn(("y", False), w.discretized_vars) + + w.width_line.setText("5") + self.assertEqual(w.var_hints[("x", False)], + VarHint(Methods.FixedWidth, ("5", ))) + self.assertEqual(w.var_hints[("y", False)], + VarHint(Methods.FixedWidth, ("5", ))) + # Check that "x" and "y" are invalidated + self.assertEqual(len(w.discretized_vars), 3) + self.assertNotIn(("x", False), w.discretized_vars) + self.assertNotIn(("y", False), w.discretized_vars) + update_disc() + self.assertEqual(len(w.discretized_vars), 5) + self.assertIn(("x", False), w.discretized_vars) + self.assertIn(("y", False), w.discretized_vars) + + select_rows(w.varview.default_view, (0, )) + w.button_group.button(Methods.FixedWidth).click() + self.assertEqual(len(w.discretized_vars), 4) + self.assertNotIn(("u", True), w.discretized_vars) + update_disc() + self.assertEqual(len(w.discretized_vars), 5) + self.assertIn(("u", True), w.discretized_vars) + + def test_discretize_var(self): + w = self.widget + self.send_signal(w.Inputs.data, self.data) + + x = self.data.domain["x"] + t = self.data.domain["t"] + + s, dvar = w._discretize_var(x, VarHint(Methods.FixedWidthTime, ("10", 0))) + self.assertIn("keep", s) + self.assertIs(dvar, x) + + s, dvar = w._discretize_var(t, VarHint(Methods.FixedWidth, ("10", ))) + self.assertIn("keep", s) + self.assertIs(dvar, t) + + try: + Options[42] = Mock() + + # Errored + # Unit test - mocked function + Options[42].function = lambda *_: "foo error" + s, dvar = w._discretize_var(t, VarHint(42, ())) + self.assertIn("foo error", s) + self.assertIsNone(dvar) + # Real error + s, dvar = w._discretize_var(t, VarHint(Methods.MDL, ())) + self.assertIn("<", s) + self.assertIsNone(dvar) + + # Removed attribute + Options[42].function = lambda *_: None + s, dvar = w._discretize_var(t, VarHint(42, ())) + self.assertEqual("", s) + self.assertIsNone(dvar) + # Really removed + s, dvar = w._discretize_var(t, VarHint(Methods.Remove, ())) + self.assertEqual("", s) + self.assertIsNone(dvar) + + # No intervals + var = Mock(compute_value=Mock(points=[])) + Options[42].function = lambda *_: var + s, dvar = w._discretize_var(t, VarHint(42, ())) + self.assertIn("removed", s) + self.assertIsNone(dvar) + s, dvar = w._discretize_var(x, VarHint(Methods.FixedWidth, ("1000", ))) + self.assertIn("removed", s) + self.assertIsNone(dvar) + + # All fine + var = Mock(compute_value=Mock(points=[1, 2, 3])) + Options[42].function = lambda *_: var + s, dvar = w._discretize_var(t, VarHint(42, ())) + self.assertIn("1, 2, 3", s) + self.assertIs(dvar, var) + s, dvar = w._discretize_var(x, VarHint(Methods.EqualWidth, (3, ))) + self.assertEqual(dvar.compute_value.points, [5, 10]) + + finally: + del Options[42] + + def test_update_discretizations(self): + w = self.widget + # Def: Keep, x: EqFreq 3, y: Keep, z: Remove, t (time): Bin 2, u (time): + w.var_hints = self.var_hints + y, t, u = map(self.domain.__getitem__, "ytu") + + # no data: do nothing, but don't crash + w._update_discretizations() + + self.send_signal(w.Inputs.data, self.data) + d = w.discretized_vars + self.assertEqual(len(d), 5) + self.assertEqual(len(d[("x", False)].values), 3) + self.assertIs(d[("y", False)], y) + self.assertIsNone(d[("z", False)]) + self.assertIsNot(d[("t", True)], t) + self.assertIsNotNone(d[("t", True)], t) + self.assertIs(d[("u", True)], u) + + d[("t", True)] = t + del d[("x", False)] + del d[("u", True)] + w._update_discretizations() + self.assertEqual(len(d[("x", False)].values), 3) + self.assertIs(d[("t", True)], t) + self.assertIs(d[("u", True)], u) + + w.var_hints[None] = VarHint(Methods.Remove, ()) + del d[("u", True)] + w._update_discretizations() + self.assertIsNone(d[("u", True)]) + + def test_copy_to_manual(self): + w = self.widget + w.var_hints = { DefaultKey: VarHint(Methods.EqualFreq, (5, )) } + self.send_signal(w.Inputs.data, self.data) + w.button_group.button(Methods.MDL).setChecked(True) + + select_rows(w.varview, (0, 2)) + self.assertTrue(w.copy_to_custom.isEnabled()) + w.copy_to_custom.click() + self.assertFalse(any(w.button_group.button(i).isChecked() + for i in Methods)) + self.assertEqual(w.var_hints[("x", False)], + VarHint(Methods.Custom, ('2.5, 7.5, 12.5', ))) + self.assertEqual(w.var_hints[("z", False)], + VarHint(Methods.Custom, ('4.5, 9.5, 14.5', ))) + self.assertNotIn(("y", False), w.var_hints) + + select_rows(w.varview, (1, )) + self.assertTrue(w.copy_to_custom.isEnabled()) + w.copy_to_custom.click() + self.assertTrue(w.button_group.button(Methods.Custom).isChecked()) + self.assertEqual(w.var_hints[("x", False)], + VarHint(Methods.Custom, ('2.5, 7.5, 12.5', ))) + self.assertEqual(w.var_hints[("z", False)], + VarHint(Methods.Custom, ('4.5, 9.5, 14.5', ))) + self.assertEqual(w.var_hints[("y", False)], + VarHint(Methods.Custom, ('3.5, 8.5, 13.5', ))) + self.assertEqual(w.threshold_line.text(), '3.5, 8.5, 13.5') + + select_rows(w.varview, (1, 4)) + w.copy_to_custom.click() + self.assertNotIn(("u", False), w.var_hints) + def test_migration_2_3(self): # Obsolete, don't want to cause confusion by public import # pylint: disable=import-outside-toplevel @@ -172,7 +435,8 @@ def test_migration_2_3(self): ({(2, 'age'): DState(method=Leave()), (2, 'rest SBP'): DState(method=EqualWidth(k=4)), (2, 'cholesterol'): DState(method=EqualFreq(k=6)), - (4, 'max HR'): DState(method=Custom(points=(1.0, 2.0, 3.0))), + (4, 'max HR'): DState( + method=Custom(points=(1.0, 2.0, 3.0))), (2, 'ST by exercise'): DState(method=MDL()), (2, 'major vessels colored'): DState(method=Default(method=EqualFreq(k=3)))}, -2), @@ -194,8 +458,8 @@ def test_migration_2_3(self): {None: VarHint(Methods.EqualFreq, (3,)), ('ST by exercise', False): VarHint(Methods.MDL, ()), ('age', False): VarHint(Methods.Keep, ()), - ('cholesterol', False): VarHint(Methods.EqualFreq, (6, )), - ('max HR', True): VarHint(Methods.Custom, (('1, 2, 3'), )), + ('cholesterol', False): VarHint(Methods.EqualFreq, (6,)), + ('max HR', True): VarHint(Methods.Custom, (('1, 2, 3'),)), ('rest SBP', False): VarHint(Methods.EqualWidth, (4,))}) @@ -215,6 +479,95 @@ def test_validate(self): self.assertEqual(v.validate("1, 2 ", 5), (v.Intermediate, "1, 2, ", 6)) +class TestModels(WidgetTest, DataMixin): + def setUp(self): + self.prepare_data() + self.widget = self.create_widget(OWDiscretize) + + def test_delegate(self): + self.prepare_data() + w = self.widget + w.var_hints = self.var_hints + # Def: Keep, x: EqFreq 3, y: Keep, z: Remove, t (time): Bin 2, u (time): + self.send_signal(w.Inputs.data, self.data) + + model = w.varview.model() + delegate: ListViewSearch.DiscDelegate = w.varview.itemDelegate() + option = QStyleOptionViewItem() + delegate.initStyleOption(option, model.index(0)) + self.assertTrue(option.font.bold()) + + option = QStyleOptionViewItem() + delegate.initStyleOption(option, model.index(4)) + self.assertFalse(option.font.bold()) + + def test_layout(self): + # Not much to test, just don't crash + self.widget.varview.updateGeometries() + + def test_model(self): + self.prepare_data() + w = self.widget + w.var_hints = self.var_hints + # Def: Keep, x: EqFreq 3, y: Keep, z: Remove, t (time): Bin 2, u (time): + self.send_signal(w.Inputs.data, self.data) + + model = w.varview.model() + display = model.index(0).data() + self.assertIn("x", display) + self.assertIn("equal", display) + self.assertIn("3", display) + self.assertIn( + str(w.discretized_vars[("x", False)].compute_value.points[0])[:3], + display) + + tooltip = model.index(0).data(Qt.ToolTipRole) + self.assertIn("x", tooltip) + self.assertIn( + str(w.discretized_vars[("x", False)].compute_value.points[0])[:3], + tooltip) + + display = model.index(1).data() + self.assertIn("y", display) + self.assertIn("keep", display) + + self.assertIsNone(model.index(1).data(Qt.ToolTipRole)) + + w.var_hints[("x", False)] = VarHint(Methods.EqualWidth, (7, )) + del w.discretized_vars[("x", False)] + w._update_discretizations() + display = model.index(0).data() + self.assertIn("x", display) + self.assertIn("equal", display) + self.assertIn("3", display) + self.assertIn( + str(w.discretized_vars[("x", False)].compute_value.points[0])[:3], + display) + + +class TestDefaultDiscModel(GuiTest): + def test_counts(self): + model = DefaultDiscModel() + self.assertEqual(model.rowCount(QModelIndex()), 1) + self.assertEqual(model.rowCount(model.index(0)), 0) + + self.assertEqual(model.columnCount(QModelIndex()), 1) + self.assertEqual(model.columnCount(model.index(0)), 0) + + def test_data(self): + model = DefaultDiscModel() + self.assertIn(format_desc(DefaultHint), model.index(0).data()) + self.assertIsInstance(model.index(0).data(Qt.DecorationRole), QIcon) + self.assertIsInstance(model.index(0).data(Qt.ToolTipRole), str) + + hint = VarHint(Methods.FixedWidth, ("314", )) + model.setData(model.index(0), hint, Qt.UserRole) + self.assertIn(format_desc(hint), model.index(0).data()) + self.assertIsInstance(model.index(0).data(Qt.DecorationRole), QIcon) + self.assertIsInstance(model.index(0).data(Qt.ToolTipRole), str) + + + class TestUtils(GuiTest): def test_show_tip(self): w = QWidget() @@ -232,9 +585,26 @@ def test_show_tip(self): show_tip(w, QPoint(100, 100), "") self.assertFalse(label.isVisible()) + def test_format_desc(self): + self.assertEqual(format_desc(VarHint(Methods.MDL, ())), + Options[Methods.MDL].short_desc) + self.assertEqual(format_desc(VarHint(Methods.EqualWidth, ("10", ))), + Options[Methods.EqualWidth].short_desc.format(10)) + self.assertEqual(format_desc(None), + Options[Methods.Default].short_desc) + + fwt = Methods.FixedWidthTime + desc = Options[fwt].short_desc.format + self.assertEqual(format_desc(VarHint(fwt, ("1", 0))), desc("1", "year")) + self.assertEqual(format_desc(VarHint(fwt, ("2", 0))), desc("2", "years")) + self.assertEqual(format_desc(VarHint(fwt, ("1", 2))), desc("1", "day")) + self.assertEqual(format_desc(VarHint(fwt, ("2", 2))), desc("2", "days")) + self.assertEqual(format_desc(VarHint(fwt, ("x", 2))), desc("x", "day(s)")) + self.assertEqual(format_desc(VarHint(fwt, ("", 2))), desc("", "day(s)")) + def test_fixed_width_disc(self): fw = partial(_fixed_width_discretization, None, None) - for arg in ("", "5.3.1", "abc"): + for arg in ("", "5.3.1", "abc", "-5", "0"): self.assertIsInstance(fw(arg), str) with patch("Orange.preprocess.discretize.FixedWidth") as disc: @@ -251,7 +621,7 @@ def test_fixed_width_disc(self): def test_fixed_time_width_disc(self): ftw = partial(_fixed_time_width_discretization, None, None) - for arg in ("", "5.3.1", "5.3", "abc"): + for arg in ("", "5.3.1", "5.3", "abc", "-5", "0"): self.assertIsInstance(ftw(arg, 1), str) with patch("Orange.preprocess.discretize.FixedTimeWidth") as disc: @@ -279,6 +649,23 @@ def test_custom_discretization(self): cd("1, 1.25, 1.5, 4") disc.assert_called_with(None, [1, 1.25, 1.5, 4]) + def test_mdl_discretization(self): + mdl = _mdl_discretization + data = Table("iris")[::10] + var = data.domain[0] + with patch("Orange.preprocess.discretize.EntropyMDL") as mdldisc: + mdl(data, var) + mdldisc.return_value.assert_called_with(data, var) + mdldisc.reset_mock() + + data = data[:, :4] + self.assertIsInstance(mdl(data, var), str) + mdldisc.assert_not_called() + + data = data.transform(Domain(data.domain[:3], data.domain[3])) + self.assertIsInstance(mdl(data, var), str) + mdldisc.assert_not_called() + def test_var_key(self): self.assertEqual(variable_key(ContinuousVariable("foo")), ("foo", False)) From 4d61c1b19ea4dfb018ba3ad608bb65ebb4844089 Mon Sep 17 00:00:00 2001 From: janezd Date: Fri, 1 Apr 2022 22:12:39 +0200 Subject: [PATCH 6/9] OWDiscretize: Update documentation --- .../source/widgets/data/discretize.md | 38 ++++++++++++------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/doc/visual-programming/source/widgets/data/discretize.md b/doc/visual-programming/source/widgets/data/discretize.md index a019c7c046a..107b0969803 100644 --- a/doc/visual-programming/source/widgets/data/discretize.md +++ b/doc/visual-programming/source/widgets/data/discretize.md @@ -1,4 +1,4 @@ -Discretize + ========== Discretizes continuous attributes from an input dataset. @@ -11,24 +11,36 @@ Discretizes continuous attributes from an input dataset. - Data: dataset with discretized values -The **Discretize** widget [discretizes](https://en.wikipedia.org/wiki/Discretization) continuous attributes with a selected method. +The **Discretize** widget [discretizes](https://en.wikipedia.org/wiki/Discretization) numeric variables. ![](images/Discretize-All-stamped.png) -1. The basic version of the widget is rather simple. It allows choosing between three different discretizations. - - [Entropy-MDL](http://ijcai.org/Past%20Proceedings/IJCAI-93-VOL2/PDF/022.pdf), invented by Fayyad and Irani is a top-down discretization, which recursively splits the attribute at a cut maximizing information gain, until the gain is lower than the minimal description length of the cut. This discretization can result in an arbitrary number of intervals, including a single interval, in which case the attribute is discarded as useless (removed). - - [Equal-frequency](http://www.saedsayad.com/unsupervised_binning.htm) splits the attribute into a given number of intervals, so that they each contain approximately the same number of instances. - - [Equal-width](https://en.wikipedia.org/wiki/Data_binning) evenly splits the range between the smallest and the largest observed value. The *Number of intervals* can be set manually. - - The widget can also be set to leave the attributes continuous or to remove them. -2. To treat attributes individually, go to **Individual Attribute Settings**. They show a specific discretization of each attribute and allow changes. First, the top left list shows the cut-off points for each attribute. In the snapshot, we used the entropy-MDL discretization, which determines the optimal number of intervals automatically; we can see it discretized the age into seven intervals with cut-offs at 21.50, 23.50, 27.50, 35.50, 43.50, 54.50 and 61.50, respectively, while the capital-gain got split into many intervals with several cut-offs. The final weight (fnlwgt), for instance, was left with a single interval and thus removed. -On the right, we can select a specific discretization method for each attribute. Attribute *“fnlwgt”* would be removed by the MDL-based discretization, so to prevent its removal, we select the attribute and choose, for instance, **Equal-frequency discretization**. We could also choose to leave the attribute continuous. -3. Produce a report. -4. Tick *Apply automatically* for the widget to automatically commit changes. Alternatively, press *Apply*. +1. Set default method for discretization. + +2. Select particular variables to set specific discretization methods. Hovering over a variable shows intervals. + +3. Discretization methods + + - **Keep numeric** keeps the variable as it is. + - **Remove** removes variable. + - **Natural binning** finds nice thresholds for the variable's range of values, for instance 10, 20, 30 or 0.2, 0.4, 0.6, 0.8. We can set the desired number of bins; the actual number will depend upon the interval. + - **Fixed width** uses a user-defined bin width. Boundaries of bins will be multiples of width. For instance, if the width is 10 and variable's values range from 35 to 68, the resulting bins will be <40, 40-50, 50-60, >60. This method does not work for time variables. If the width is too large (resulting in a single interval) or too small (resulting in more than 100 intervals), the variable is removed. + - **Time interval** is similar to Fixed width, but for time variables. We specify the width and a time unit, e.g. 4 months or 3 days. Bin boundaries will be multiples of the interval; e.g. with 4 months, bins will always include Jan-Mar, Apr-Jun, Jul-Sep and Oct-Dec. + - **[Equal-frequency]**(http://www.saedsayad.com/unsupervised_binning.htm) splits the attribute into the given number of intervals with approximately the same number of instances. + - [Equal-width](https://en.wikipedia.org/wiki/Data_binning) evenly splits the range between the smallest and the largest observed value. + - [Entropy-MDL](http://ijcai.org/Past%20Proceedings/IJCAI-93-VOL2/PDF/022.pdf), is a top-down discretization invented by Fayyad and Irani, which recursively splits the attribute at a cut maximizing information gain, until the gain is lower than the minimal description length of the cut. This discretization can result in an arbitrary number of intervals, including a single interval, in which case the variable is discarded as useless (removed). + - **Custom** allows entering an increasing, comma-separated list of thresholds. This is not applicable to time variables. + - **Use default setting** (enabled for particular settings and not default) sets the method to specified as "Default setting". + +4. The CC button sets the method for the currently selected variables to Custom, using their current thresholds. This allows for manual editing of automatically determined bins. Example ------- -In the schema below, we show the *Iris* dataset with continuous attributes -(as in the original data file) and with discretized attributes. +In the schema below, we tool the *Heart disease* data set and +- discretized *age* to a fixed interval of 10 (years), +- *max HR* to approximately 6 bins (this closest match were 7 bins with a width of 25), +- removed *Cholesterol*, +- and used *entropy-mdl* for remaining variables, which resulted in removing *rest SBP* and in two intervals for *ST by exercise* and *major vessels colored*. ![](images/Discretize-Example.png) From 86b10c09c04fb66f04454f98826eb67de5e3117c Mon Sep 17 00:00:00 2001 From: janezd Date: Sun, 10 Apr 2022 23:42:07 +0200 Subject: [PATCH 7/9] OWDiscretize: Disable copy-to-custom when default is selected --- Orange/widgets/data/owdiscretize.py | 3 +++ Orange/widgets/data/tests/test_owdiscretize.py | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 625582096fc..298bb5828ec 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -882,6 +882,7 @@ def _default_selected(self, selected): set_enabled(Methods.FixedWidth, True) set_enabled(Methods.FixedWidthTime, True) set_enabled(Methods.Custom, True) + self.copy_to_custom.setEnabled(False) def _var_selection_changed(self, _): """Callback for changed selection in listview with variables""" @@ -900,6 +901,7 @@ def _var_selection_changed(self, _): set_enabled(Methods.Default, True) set_enabled(Methods.FixedWidth, no_time) set_enabled(Methods.Custom, no_time) + self.copy_to_custom.setEnabled(no_time) set_enabled(Methods.FixedWidthTime, all_time) def _update_interface(self): @@ -937,6 +939,7 @@ def set_data(self, data: Optional[Table]): self.varview.model().set_domain(None if data is None else data.domain) self._update_discretizations() self._update_default_model() + self.varview.select_default() self._set_mdl_button() self.commit.now() diff --git a/Orange/widgets/data/tests/test_owdiscretize.py b/Orange/widgets/data/tests/test_owdiscretize.py index f69cbd48537..2fb0979c225 100644 --- a/Orange/widgets/data/tests/test_owdiscretize.py +++ b/Orange/widgets/data/tests/test_owdiscretize.py @@ -198,6 +198,7 @@ def test_change_selection_update_interface(self): self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) self.assertFalse(w.button_group.button(Methods.FixedWidthTime).isEnabled()) self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + self.assertTrue(w.copy_to_custom.isEnabled()) self.assertEqual(w.width_line.text(), "10") select_rows(w.varview, (1, 2)) @@ -205,6 +206,7 @@ def test_change_selection_update_interface(self): self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) self.assertFalse(w.button_group.button(Methods.FixedWidthTime).isEnabled()) self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + self.assertTrue(w.copy_to_custom.isEnabled()) select_rows(w.varview, (2, 4)) self.assertFalse(w.button_group.button(Methods.FixedWidth).isChecked()) @@ -217,6 +219,7 @@ def test_change_selection_update_interface(self): self.assertFalse(w.button_group.button(Methods.FixedWidth).isEnabled()) self.assertTrue(w.button_group.button(Methods.FixedWidthTime).isEnabled()) self.assertFalse(w.button_group.button(Methods.Custom).isEnabled()) + self.assertFalse(w.copy_to_custom.isEnabled()) select_rows(w.varview.default_view, (0, )) self.assertEqual(len(w.varview.selectionModel().selectedIndexes()), 0) @@ -224,6 +227,7 @@ def test_change_selection_update_interface(self): self.assertTrue(w.button_group.button(Methods.FixedWidth).isEnabled()) self.assertTrue(w.button_group.button(Methods.FixedWidthTime).isEnabled()) self.assertTrue(w.button_group.button(Methods.Custom).isEnabled()) + self.assertFalse(w.copy_to_custom.isEnabled()) self.assertFalse(w.button_group.button(Methods.Default).isEnabled()) w._check_button(Methods.FixedWidth, True) self.assertTrue(w.button_group.button(Methods.FixedWidth).isChecked()) From 470d0b8b330a85056609c9a4839e2b9af79e845d Mon Sep 17 00:00:00 2001 From: Ajda Date: Wed, 6 Apr 2022 09:23:00 +0200 Subject: [PATCH 8/9] [DOC] Discretize: fixes --- .../source/widgets/data/discretize.md | 22 +++++++++--------- .../data/images/Discretize-All-stamped.png | Bin 24113 -> 0 bytes .../widgets/data/images/Discretize-All.png | Bin 22335 -> 0 bytes .../data/images/Discretize-Example.png | Bin 138248 -> 155774 bytes .../source/widgets/data/images/Discretize.png | Bin 0 -> 45425 bytes 5 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 doc/visual-programming/source/widgets/data/images/Discretize-All-stamped.png delete mode 100644 doc/visual-programming/source/widgets/data/images/Discretize-All.png create mode 100644 doc/visual-programming/source/widgets/data/images/Discretize.png diff --git a/doc/visual-programming/source/widgets/data/discretize.md b/doc/visual-programming/source/widgets/data/discretize.md index 107b0969803..d58557bf292 100644 --- a/doc/visual-programming/source/widgets/data/discretize.md +++ b/doc/visual-programming/source/widgets/data/discretize.md @@ -1,7 +1,7 @@ - +Discretize ========== -Discretizes continuous attributes from an input dataset. +Converts numeric attributes to categorical. **Inputs** @@ -13,22 +13,22 @@ Discretizes continuous attributes from an input dataset. The **Discretize** widget [discretizes](https://en.wikipedia.org/wiki/Discretization) numeric variables. -![](images/Discretize-All-stamped.png) +![](images/Discretize.png) 1. Set default method for discretization. -2. Select particular variables to set specific discretization methods. Hovering over a variable shows intervals. +2. Select variables to set specific discretization methods for each. Hovering over a variable shows intervals. 3. Discretization methods - **Keep numeric** keeps the variable as it is. - **Remove** removes variable. - - **Natural binning** finds nice thresholds for the variable's range of values, for instance 10, 20, 30 or 0.2, 0.4, 0.6, 0.8. We can set the desired number of bins; the actual number will depend upon the interval. - - **Fixed width** uses a user-defined bin width. Boundaries of bins will be multiples of width. For instance, if the width is 10 and variable's values range from 35 to 68, the resulting bins will be <40, 40-50, 50-60, >60. This method does not work for time variables. If the width is too large (resulting in a single interval) or too small (resulting in more than 100 intervals), the variable is removed. + - **Natural binning** finds nice thresholds for the variable's range of values, for instance 10, 20, 30 or 0.2, 0.4, 0.6, 0.8. We can set the desired number of bins; the actual number will depend on the interval. + - **Fixed width** uses a user-defined bin width. Boundaries of bins will be multiples of width. For instance, if the width is 10 and the variable's values range from 35 to 68, the resulting bins will be <40, 40-50, 50-60, >60. This method does not work for time variables. If the width is too large (resulting in a single interval) or too small (resulting in more than 100 intervals), the variable is removed. - **Time interval** is similar to Fixed width, but for time variables. We specify the width and a time unit, e.g. 4 months or 3 days. Bin boundaries will be multiples of the interval; e.g. with 4 months, bins will always include Jan-Mar, Apr-Jun, Jul-Sep and Oct-Dec. - - **[Equal-frequency]**(http://www.saedsayad.com/unsupervised_binning.htm) splits the attribute into the given number of intervals with approximately the same number of instances. + - **[Equal-frequency](http://www.saedsayad.com/unsupervised_binning.htm)** splits the attribute into a given number of intervals with approximately the same number of instances. - [Equal-width](https://en.wikipedia.org/wiki/Data_binning) evenly splits the range between the smallest and the largest observed value. - - [Entropy-MDL](http://ijcai.org/Past%20Proceedings/IJCAI-93-VOL2/PDF/022.pdf), is a top-down discretization invented by Fayyad and Irani, which recursively splits the attribute at a cut maximizing information gain, until the gain is lower than the minimal description length of the cut. This discretization can result in an arbitrary number of intervals, including a single interval, in which case the variable is discarded as useless (removed). + - [Entropy-MDL](http://ijcai.org/Past%20Proceedings/IJCAI-93-VOL2/PDF/022.pdf) is a top-down discretization invented by Fayyad and Irani, which recursively splits the attribute at a cut maximizing information gain, until the gain is lower than the minimal description length of the cut. This discretization can result in an arbitrary number of intervals, including a single interval, in which case the variable is discarded as useless (removed). - **Custom** allows entering an increasing, comma-separated list of thresholds. This is not applicable to time variables. - **Use default setting** (enabled for particular settings and not default) sets the method to specified as "Default setting". @@ -37,10 +37,10 @@ The **Discretize** widget [discretizes](https://en.wikipedia.org/wiki/Discretiza Example ------- -In the schema below, we tool the *Heart disease* data set and +In the schema below, we took the *Heart disease* data set and - discretized *age* to a fixed interval of 10 (years), -- *max HR* to approximately 6 bins (this closest match were 7 bins with a width of 25), +- *max HR* to approximately 6 bins (the closest match were 7 bins with a width of 25), - removed *Cholesterol*, -- and used *entropy-mdl* for remaining variables, which resulted in removing *rest SBP* and in two intervals for *ST by exercise* and *major vessels colored*. +- and used *entropy-mdl* for the remaining variables, which resulted in removing *rest SBP* and in two intervals for *ST by exercise* and *major vessels colored*. ![](images/Discretize-Example.png) diff --git a/doc/visual-programming/source/widgets/data/images/Discretize-All-stamped.png b/doc/visual-programming/source/widgets/data/images/Discretize-All-stamped.png deleted file mode 100644 index a504dbe4698a36fb997c867f984072028305892f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24113 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 diff --git a/doc/visual-programming/source/widgets/data/images/Discretize-Example.png b/doc/visual-programming/source/widgets/data/images/Discretize-Example.png index 67dc0540deb234dc1d799dd6ce7fe1c2e02968d4..3db56a32d894d52def32c60a7c67338f64efb908 100644 GIT binary patch literal 155774 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 z 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

@ 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

L@qKs;$lpPgW6=Afq8Z;3D#(Rn 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 z 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�g@10?l1X-(H}ICB*{=hH>f%viM+jud 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 literal 138248 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 C-`kl0 diff --git a/doc/visual-programming/source/widgets/data/images/Discretize.png b/doc/visual-programming/source/widgets/data/images/Discretize.png new file mode 100644 index 0000000000000000000000000000000000000000..11f80cf05c8ca815bfe838a934b6987dbf68bd87 GIT binary patch literal 45425 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 Date: Fri, 22 Apr 2022 18:44:37 +0200 Subject: [PATCH 9/9] OWDiscretize: Add idClicked signal for PyQt < 5.15 --- Orange/widgets/data/owdiscretize.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Orange/widgets/data/owdiscretize.py b/Orange/widgets/data/owdiscretize.py index 298bb5828ec..d9b5de8fc79 100644 --- a/Orange/widgets/data/owdiscretize.py +++ b/Orange/widgets/data/owdiscretize.py @@ -4,7 +4,8 @@ from typing import Optional, Tuple, Union, Callable, NamedTuple, Dict, List from AnyQt.QtCore import ( - Qt, QTimer, QPoint, QItemSelectionModel, QSize, QAbstractListModel) + Qt, QTimer, QPoint, QItemSelectionModel, QSize, QAbstractListModel, + pyqtSignal as Signal) from AnyQt.QtGui import ( QValidator, QPalette, QDoubleValidator, QIntValidator, QColor) from AnyQt.QtWidgets import ( @@ -26,6 +27,17 @@ from Orange.widgets.data.oweditdomain import FixedSizeButton +# Remove this when we require PyQt 5.15 +if not hasattr(QButtonGroup, "idClicked"): + class QButtonGroup(QButtonGroup): # pylint: disable=function-redefined + idClicked = Signal(int) + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.buttonClicked.connect( + lambda button: self.idClicked.emit(self.id(button))) + + re_custom_sep = re.compile(r"\s*,\s*") time_units = ["year", "month", "day", "week", "hour", "minute", "second"] INVALID_WIDTH = "invalid width"