diff --git a/Orange/widgets/visualize/owsilhouetteplot.py b/Orange/widgets/visualize/owsilhouetteplot.py
index e0a2b169048..df660aaa273 100644
--- a/Orange/widgets/visualize/owsilhouetteplot.py
+++ b/Orange/widgets/visualize/owsilhouetteplot.py
@@ -177,6 +177,11 @@ def __init__(self):
ibox.setFixedWidth(ibox.sizeHint().width())
warning.setVisible(False)
+ # box displaying the average silhouette score
+ avg_box = gui.vBox(self.controlArea, "Average Silhouette Score")
+ self.avg_silhouette_label = gui.widgetLabel(avg_box, "")
+ self._update_avg_silhouette()
+
gui.rubber(self.controlArea)
gui.auto_send(self.buttonsArea, self, "auto_commit")
@@ -292,6 +297,7 @@ def clear(self):
self._clear_scene()
self.Error.clear()
self.Warning.clear()
+ self._update_avg_silhouette() # Update the average silhouette display
def _clear_scene(self):
# Clear the graphics scene and associated objects
@@ -340,6 +346,15 @@ def _ensure_matrix(self):
else:
assert False, "invalid state"
+ def _update_avg_silhouette(self):
+ # update the average silhouette score
+ if self._silhouette is not None and len(self._silhouette) > 0:
+ avg_score = np.mean(self._silhouette)
+ self.avg_silhouette_label.setText(
+ f"Silhouette: {avg_score:.4f}")
+ else:
+ self.avg_silhouette_label.setText("Silhouette: N/A")
+
def _update(self):
# Update/recompute the effective distances and scores as required.
self._clear_messages()
@@ -384,6 +399,8 @@ def _update(self):
self.Warning.nan_distances(
count_nandist, s="s" if count_nandist > 1 else "")
+ self._update_avg_silhouette() # Update the average silhouette display
+
def _reset_all(self):
self._mask = None
self._silhouette = None
diff --git a/Orange/widgets/visualize/tests/test_owsilhouetteplot.py b/Orange/widgets/visualize/tests/test_owsilhouetteplot.py
index 3674722b61e..e0c1d475a9f 100644
--- a/Orange/widgets/visualize/tests/test_owsilhouetteplot.py
+++ b/Orange/widgets/visualize/tests/test_owsilhouetteplot.py
@@ -302,6 +302,18 @@ def test_migration(self):
self.assertEqual(context.values["cluster_var"], ("cfoo", 101))
self.assertNotIn("annotation_var_idx", values)
+ def test_average_silhouette_score(self):
+ data = Table("brown-selected")
+ self.send_signal(self.widget.Inputs.data, data)
+ self.assertEqual(self.widget.avg_silhouette_label.text(),
+ "Silhouette: 0.4692")
+ self.send_signal(self.widget.Inputs.data, None)
+ self.assertEqual(self.widget.avg_silhouette_label.text(),
+ "Silhouette: N/A")
+ self.send_signal(self.widget.Inputs.data, data)
+ self.assertEqual(self.widget.avg_silhouette_label.text(),
+ "Silhouette: 0.4692")
+
if __name__ == "__main__":
unittest.main()