Skip to content

Commit 8de1497

Browse files
committed
Merge pull request #1937 from janezd/fix-impute-fail
[FIX] Impute: Fix crash when model-based imputation fails (cherry picked from commit bb58be8)
1 parent a36277d commit 8de1497

File tree

2 files changed

+38
-11
lines changed

2 files changed

+38
-11
lines changed

Orange/widgets/data/owimpute.py

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
from Orange.widgets import gui, settings
1515
from Orange.widgets.utils import itemmodels
1616
from Orange.widgets.utils.sql import check_sql_input
17-
from Orange.widgets.widget import OWWidget
17+
from Orange.widgets.widget import OWWidget, Msg
1818
from Orange.classification import SimpleTreeLearner
1919

2020

@@ -61,6 +61,9 @@ class OWImpute(OWWidget):
6161
("Learner", Learner, "set_learner")]
6262
outputs = [("Data", Orange.data.Table)]
6363

64+
class Error(OWWidget.Error):
65+
imputation_failed = Msg("Imputation failed for '{}'")
66+
6467
DEFAULT_LEARNER = SimpleTreeLearner()
6568
METHODS = [AsDefault(), impute.DoNotImpute(), impute.Average(),
6669
impute.AsValue(), impute.Model(DEFAULT_LEARNER), impute.Random(),
@@ -251,17 +254,23 @@ def commit(self):
251254
class_vars = []
252255

253256
self.warning()
257+
self.Error.imputation_failed.clear()
254258
with self.progressBar(len(self.varmodel)) as progress:
255259
for i, var in enumerate(self.varmodel):
256260
method = self.variable_methods.get(i, self.default_method)
257261

258-
if not method.supports_variable(var):
259-
self.warning("Default method can not handle '{}'".
260-
format(var.name))
261-
elif isinstance(method, impute.DropInstances):
262-
drop_mask |= method(self.data, var)
263-
else:
264-
var = method(self.data, var)
262+
try:
263+
if not method.supports_variable(var):
264+
self.warning("Default method can not handle '{}'".
265+
format(var.name))
266+
elif isinstance(method, impute.DropInstances):
267+
drop_mask |= method(self.data, var)
268+
else:
269+
var = method(self.data, var)
270+
except:
271+
self.Error.imputation_failed(var.name)
272+
attributes = class_vars = None
273+
break
265274

266275
if isinstance(var, Orange.data.Variable):
267276
var = [var]
@@ -273,9 +282,12 @@ def commit(self):
273282

274283
progress.advance()
275284

276-
domain = Orange.data.Domain(attributes, class_vars,
277-
self.data.domain.metas)
278-
data = self.data.from_table(domain, self.data[~drop_mask])
285+
if attributes is None:
286+
data = None
287+
else:
288+
domain = Orange.data.Domain(attributes, class_vars,
289+
self.data.domain.metas)
290+
data = self.data.from_table(domain, self.data[~drop_mask])
279291

280292
self.send("Data", data)
281293
self.modified = False

Orange/widgets/data/tests/test_owimpute.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,18 @@ def test_empty_data(self):
2828
widget.unconditional_commit()
2929
imp_data = self.get_output("Data")
3030
self.assertEqual(len(imp_data), 0)
31+
32+
def test_no_features(self):
33+
widget = self.widget
34+
widget.default_method_index = widget.MODEL_BASED_IMPUTER
35+
widget.default_method = widget.METHODS[widget.default_method_index]
36+
37+
self.send_signal("Data", Table("iris"))
38+
39+
self.send_signal("Learner", lambda *_: 1/0) # Learner fails
40+
widget.unconditional_commit()
41+
self.assertTrue(widget.Error.imputation_failed.is_shown())
42+
43+
self.send_signal("Learner", lambda *_: (lambda *_: 1/0)) # Model fails
44+
widget.unconditional_commit()
45+
self.assertTrue(widget.Error.imputation_failed.is_shown())

0 commit comments

Comments
 (0)