diff --git a/Orange/widgets/data/owimpute.py b/Orange/widgets/data/owimpute.py index f14d5ff7986..b10d70506aa 100644 --- a/Orange/widgets/data/owimpute.py +++ b/Orange/widgets/data/owimpute.py @@ -14,7 +14,7 @@ from Orange.widgets import gui, settings from Orange.widgets.utils import itemmodels from Orange.widgets.utils.sql import check_sql_input -from Orange.widgets.widget import OWWidget +from Orange.widgets.widget import OWWidget, Msg from Orange.classification import SimpleTreeLearner @@ -61,6 +61,9 @@ class OWImpute(OWWidget): ("Learner", Learner, "set_learner")] outputs = [("Data", Orange.data.Table)] + class Error(OWWidget.Error): + imputation_failed = Msg("Imputation failed for '{}'") + DEFAULT_LEARNER = SimpleTreeLearner() METHODS = [AsDefault(), impute.DoNotImpute(), impute.Average(), impute.AsValue(), impute.Model(DEFAULT_LEARNER), impute.Random(), @@ -251,17 +254,23 @@ def commit(self): class_vars = [] self.warning() + self.Error.imputation_failed.clear() with self.progressBar(len(self.varmodel)) as progress: for i, var in enumerate(self.varmodel): method = self.variable_methods.get(i, self.default_method) - if not method.supports_variable(var): - self.warning("Default method can not handle '{}'". - format(var.name)) - elif isinstance(method, impute.DropInstances): - drop_mask |= method(self.data, var) - else: - var = method(self.data, var) + try: + if not method.supports_variable(var): + self.warning("Default method can not handle '{}'". + format(var.name)) + elif isinstance(method, impute.DropInstances): + drop_mask |= method(self.data, var) + else: + var = method(self.data, var) + except: + self.Error.imputation_failed(var.name) + attributes = class_vars = None + break if isinstance(var, Orange.data.Variable): var = [var] @@ -273,9 +282,12 @@ def commit(self): progress.advance() - domain = Orange.data.Domain(attributes, class_vars, - self.data.domain.metas) - data = self.data.from_table(domain, self.data[~drop_mask]) + if attributes is None: + data = None + else: + domain = Orange.data.Domain(attributes, class_vars, + self.data.domain.metas) + data = self.data.from_table(domain, self.data[~drop_mask]) self.send("Data", data) self.modified = False diff --git a/Orange/widgets/data/tests/test_owimpute.py b/Orange/widgets/data/tests/test_owimpute.py index 067a1dd6d35..53bd440cc4a 100644 --- a/Orange/widgets/data/tests/test_owimpute.py +++ b/Orange/widgets/data/tests/test_owimpute.py @@ -28,3 +28,18 @@ def test_empty_data(self): widget.unconditional_commit() imp_data = self.get_output("Data") self.assertEqual(len(imp_data), 0) + + def test_no_features(self): + widget = self.widget + widget.default_method_index = widget.MODEL_BASED_IMPUTER + widget.default_method = widget.METHODS[widget.default_method_index] + + self.send_signal("Data", Table("iris")) + + self.send_signal("Learner", lambda *_: 1/0) # Learner fails + widget.unconditional_commit() + self.assertTrue(widget.Error.imputation_failed.is_shown()) + + self.send_signal("Learner", lambda *_: (lambda *_: 1/0)) # Model fails + widget.unconditional_commit() + self.assertTrue(widget.Error.imputation_failed.is_shown())