Skip to content

Commit c1ef16e

Browse files
committed
Predictions: Handle discrete target with no values
1 parent f61b322 commit c1ef16e

File tree

5 files changed

+49
-10
lines changed

5 files changed

+49
-10
lines changed

Orange/base.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,13 +259,13 @@ def backmap_value(self, value, mapped_probs, n_values, backmappers):
259259

260260
value = backmapper(value)
261261
nans = np.isnan(value)
262-
if not np.any(nans):
262+
if not np.any(nans) or n_values[0] < 2:
263263
return value
264264
if mapped_probs is not None:
265265
value[nans] = np.argmax(mapped_probs[nans], axis=1)
266266
else:
267-
value[nans] = np.RandomState(0).choice(
268-
backmapper(np.arange(0, n_values[0] - 1))
267+
value[nans] = np.random.RandomState(0).choice(
268+
backmapper(np.arange(0, n_values[0] - 1)),
269269
(np.sum(nans), ))
270270
return value
271271

Orange/widgets/evaluate/owconfusionmatrix.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ class Outputs:
118118
class Error(widget.OWWidget.Error):
119119
no_regression = Msg("Confusion Matrix cannot show regression results.")
120120
invalid_values = Msg("Evaluation Results input contains invalid values")
121+
empty_input = widget.Msg("Empty result on input. Nothing to display.")
121122

122123
def __init__(self):
123124
super().__init__()
@@ -245,11 +246,14 @@ def set_results(self, results):
245246
if results is not None and results.data is not None:
246247
data = results.data[results.row_indices]
247248

249+
self.Error.no_regression.clear()
250+
self.Error.empty_input.clear()
248251
if data is not None and not data.domain.has_discrete_class:
249252
self.Error.no_regression()
250253
data = results = None
251-
else:
252-
self.Error.no_regression.clear()
254+
elif results is not None and not results.actual.size:
255+
self.Error.empty_input()
256+
data = results = None
253257

254258
nan_values = False
255259
if results is not None:

Orange/widgets/evaluate/owrocanalysis.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -303,10 +303,6 @@ class OWROCAnalysis(widget.OWWidget):
303303
class Inputs:
304304
evaluation_results = Input("Evaluation Results", Orange.evaluation.Results)
305305

306-
class Warning(widget.OWWidget.Warning):
307-
empty_results = widget.Msg(
308-
"Empty results on input. There is nothing to display.")
309-
310306
target_index = settings.Setting(0)
311307
selected_classifiers = []
312308

Orange/widgets/evaluate/tests/test_owpredictions.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,12 @@
77
from Orange.data.io import TabReader
88
from Orange.widgets.tests.base import WidgetTest
99
from Orange.widgets.evaluate.owpredictions import OWPredictions
10+
from Orange.widgets.evaluate.owcalibrationplot import OWCalibrationPlot
11+
from Orange.widgets.evaluate.owconfusionmatrix import OWConfusionMatrix
12+
from Orange.widgets.evaluate.owliftcurve import OWLiftCurve
13+
from Orange.widgets.evaluate.owrocanalysis import OWROCAnalysis
1014

11-
from Orange.data import Table, Domain
15+
from Orange.data import Table, Domain, DiscreteVariable
1216
from Orange.modelling import ConstantLearner, TreeLearner
1317
from Orange.evaluation import Results
1418
from Orange.widgets.tests.utils import excepthook_catch
@@ -49,6 +53,38 @@ def test_nan_target_input(self):
4953
evres = self.get_output(self.widget.Outputs.evaluation_results)
5054
self.assertEqual(len(evres.data), 0)
5155

56+
def test_no_values_target(self):
57+
train = Table("titanic")
58+
model = ConstantLearner()(train)
59+
self.send_signal(self.widget.Inputs.predictors, model)
60+
domain = Domain([DiscreteVariable("status", values=["first", "third"]),
61+
DiscreteVariable("age", values=["adult", "child"]),
62+
DiscreteVariable("sex", values=["female", "male"])],
63+
[DiscreteVariable("survived", values=[])])
64+
test = Table(domain, np.array([[0, 0, 1], [0, 1, 0], [1, 0, 0]]),
65+
np.full((3, 1), np.nan))
66+
self.send_signal(self.widget.Inputs.data, test)
67+
pred = self.get_output(self.widget.Outputs.predictions)
68+
self.assertEqual(len(pred), len(test))
69+
70+
results = self.get_output(self.widget.Outputs.evaluation_results)
71+
72+
cm_widget = self.create_widget(OWConfusionMatrix)
73+
self.send_signal(cm_widget.Inputs.evaluation_results, results,
74+
widget=cm_widget)
75+
76+
ra_widget = self.create_widget(OWROCAnalysis)
77+
self.send_signal(ra_widget.Inputs.evaluation_results, results,
78+
widget=ra_widget)
79+
80+
lc_widget = self.create_widget(OWLiftCurve)
81+
self.send_signal(lc_widget.Inputs.evaluation_results, results,
82+
widget=lc_widget)
83+
84+
cp_widget = self.create_widget(OWCalibrationPlot)
85+
self.send_signal(cp_widget.Inputs.evaluation_results, results,
86+
widget=cp_widget)
87+
5288
def test_mismatching_targets(self):
5389
warning = self.widget.Warning
5490

Orange/widgets/evaluate/utils.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ def anynan(a):
3232
elif not results.data.domain.has_discrete_class:
3333
error_group.invalid_results(
3434
"Discrete outcome variable is required")
35+
elif not results.actual.size:
36+
error_group.invalid_results(
37+
"Empty result on input. Nothing to display.")
3538
elif check_nan and (anynan(results.actual) or
3639
anynan(results.predicted) or
3740
(results.probabilities is not None and

0 commit comments

Comments
 (0)