Skip to content

Commit 985b758

Browse files
committed
comments
1 parent ee9e552 commit 985b758

2 files changed

Lines changed: 27 additions & 1 deletion

File tree

skrub/_reporting/_plotting.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,34 @@ def _get_range(values, frac=0.2, factor=3.0):
200200

201201

202202
def _get_safe_hist_range(values):
203-
# make sure numpy can find bin edges between the range low and high bounds
203+
# Get a safe min, max range for the histogram (the 'range' parameter of
204+
# np.histogram).
205+
#
206+
# This handles a corner case where the range of the data is very narrow and
207+
# there are less than 10 (the default number of bins) representable
208+
# floating-point numbers between the data min and max (with the precision
209+
# of the input column dtype). In this case numpy/matplotlib histogram with
210+
# default parameters fails, so we pass the 'range' parameter to extend it
211+
# slightly beyond the data range so that it is wide enough to contain 10
212+
# bins.
204213
if not len(values) or not (
205214
np.issubdtype(values.dtype, np.floating)
206215
or np.issubdtype(values.dtype, np.integer)
207216
):
217+
# empty or non-numeric inputs (datetimes) need no special handling.
208218
return None
209219
vmin, vmax = values.min(), values.max()
210220
delta = max(np.spacing(vmin), np.spacing(vmax))
211221
if vmax - vmin > 12 * delta:
222+
# Min and max are far enough to divide the data range into 10 bins, we
223+
# can keep the default range=None.
224+
#
225+
# 12 is a bit conservative, 10 is probably enough, but there is no
226+
# harm in having the plot range slightly wider than is strictly
227+
# required.
212228
return None
229+
# Extend the range by 12 spacing steps (6 on each side) so the new range
230+
# can contain the bins.
213231
return vmin - 6 * delta, vmax + 6 * delta
214232

215233

skrub/_reporting/tests/test_plotting.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,18 @@ def test_histogram():
2929
_, hist = _plotting.histogram(data)
3030
assert (hist["n_low_outliers"], hist["n_high_outliers"]) == (0, 0)
3131

32+
# Test a column with values very close to each other.
33+
# There are less than 10 (default number of histogram bins) representable
34+
# floating-point numbers in the range, which would cause numpy or
35+
# matplotlib histogram to raise an exception without appropriate handling
36+
# in skrub.
3237
low = np.float32(10.0)
3338
high = np.nextafter(low, 11.0)
39+
3440
data = pd.Series([low, high])
3541
_, hist = _plotting.histogram(data)
42+
assert hist["n_low_outliers"] == 0
43+
assert hist["n_high_outliers"] == 0
3644

3745
# all infinite. +- inf are outliers
3846
data = pd.Series(

0 commit comments

Comments
 (0)