diff --git a/src/evaluate/visualization.py b/src/evaluate/visualization.py index b8be8605..19bbc707 100644 --- a/src/evaluate/visualization.py +++ b/src/evaluate/visualization.py @@ -184,12 +184,11 @@ def radar_plot(data, model_names, invert_range=[], config=None, fig=None): if all(x in variables for x in invert_range) is False: raise ValueError("All of the metrics in `invert_range` should be in the data provided.") min_max_per_variable = data.describe().T[["min", "max"]] - min_max_per_variable["min"] = min_max_per_variable["min"] - 0.1 * ( - min_max_per_variable["max"] - min_max_per_variable["min"] - ) - min_max_per_variable["max"] = min_max_per_variable["max"] + 0.1 * ( - min_max_per_variable["max"] - min_max_per_variable["min"] - ) + padding = 0.1 * (min_max_per_variable["max"] - min_max_per_variable["min"]) + # variables that take a single value across all models would otherwise get a zero-width range + padding = padding.where(padding > 0, 0.1) + min_max_per_variable["min"] = min_max_per_variable["min"] - padding + min_max_per_variable["max"] = min_max_per_variable["max"] + padding ranges = list(min_max_per_variable.itertuples(index=False, name=None)) ranges = [ diff --git a/tests/test_viz.py b/tests/test_viz.py index c44e5104..b6bd7de8 100644 --- a/tests/test_viz.py +++ b/tests/test_viz.py @@ -1,6 +1,7 @@ from unittest import TestCase import matplotlib.pyplot as plt +import numpy as np from evaluate.visualization import radar_plot @@ -22,3 +23,23 @@ def test_output_is_plot(self): invert_range = ["latency_in_seconds"] out_plt = radar_plot(data, model_names, invert_range) self.assertIsInstance(out_plt, plt.Figure) + + def test_range_padding_is_symmetric(self): + data = [{"accuracy": 0.0, "precision": 1.0}, {"accuracy": 10.0, "precision": 2.0}] + model_names = ["model1", "model2"] + out_plt = radar_plot(data, model_names) + # the accuracy values span 10, so both ends of its axis are padded by 1 + low, high = out_plt.axes[0].get_ylim() + self.assertAlmostEqual(low, -1.0) + self.assertAlmostEqual(high, 11.0) + + def test_metric_with_identical_values(self): + data = [{"accuracy": 0.9, "precision": 0.8}, {"accuracy": 0.9, "precision": 0.6}] + model_names = ["model1", "model2"] + out_plt = radar_plot(data, model_names) + # accuracy is identical for both models, but precision is not, so the two + # plotted shapes must still differ from each other + first, second = (line.get_ydata() for line in out_plt.axes[1].lines) + self.assertTrue(np.isfinite(first).all()) + self.assertTrue(np.isfinite(second).all()) + self.assertFalse(np.array_equal(first, second))