From 489d409c651fe71d4695d8600d0219b249886315 Mon Sep 17 00:00:00 2001 From: "JHM Darbyshire (iMac)" Date: Tue, 13 Apr 2021 17:29:42 +0200 Subject: [PATCH] restructure highlight_between --- pandas/io/formats/style.py | 95 ++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/pandas/io/formats/style.py b/pandas/io/formats/style.py index 9b4673ddb7906..f51f81d7c3504 100644 --- a/pandas/io/formats/style.py +++ b/pandas/io/formats/style.py @@ -1558,55 +1558,10 @@ def highlight_between( .. figure:: ../../_static/style/hbetw_props.png """ - - def f( - data: FrameOrSeries, - props: str, - left: Scalar | Sequence | np.ndarray | FrameOrSeries | None = None, - right: Scalar | Sequence | np.ndarray | FrameOrSeries | None = None, - inclusive: bool | str = True, - ) -> np.ndarray: - if np.iterable(left) and not isinstance(left, str): - left = _validate_apply_axis_arg( - left, "left", None, data # type: ignore[arg-type] - ) - - if np.iterable(right) and not isinstance(right, str): - right = _validate_apply_axis_arg( - right, "right", None, data # type: ignore[arg-type] - ) - - # get ops with correct boundary attribution - if inclusive == "both": - ops = (operator.ge, operator.le) - elif inclusive == "neither": - ops = (operator.gt, operator.lt) - elif inclusive == "left": - ops = (operator.ge, operator.lt) - elif inclusive == "right": - ops = (operator.gt, operator.le) - else: - raise ValueError( - f"'inclusive' values can be 'both', 'left', 'right', or 'neither' " - f"got {inclusive}" - ) - - g_left = ( - ops[0](data, left) - if left is not None - else np.full(data.shape, True, dtype=bool) - ) - l_right = ( - ops[1](data, right) - if right is not None - else np.full(data.shape, True, dtype=bool) - ) - return np.where(g_left & l_right, props, "") - if props is None: props = f"background-color: {color};" return self.apply( - f, # type: ignore[arg-type] + _highlight_between, # type: ignore[arg-type] axis=axis, subset=subset, props=props, @@ -1831,3 +1786,51 @@ def css(rgba) -> str: index=data.index, columns=data.columns, ) + + +def _highlight_between( + data: FrameOrSeries, + props: str, + left: Scalar | Sequence | np.ndarray | FrameOrSeries | None = None, + right: Scalar | Sequence | np.ndarray | FrameOrSeries | None = None, + inclusive: bool | str = True, +) -> np.ndarray: + """ + Return an array of css props based on condition of data values within given range. + """ + if np.iterable(left) and not isinstance(left, str): + left = _validate_apply_axis_arg( + left, "left", None, data # type: ignore[arg-type] + ) + + if np.iterable(right) and not isinstance(right, str): + right = _validate_apply_axis_arg( + right, "right", None, data # type: ignore[arg-type] + ) + + # get ops with correct boundary attribution + if inclusive == "both": + ops = (operator.ge, operator.le) + elif inclusive == "neither": + ops = (operator.gt, operator.lt) + elif inclusive == "left": + ops = (operator.ge, operator.lt) + elif inclusive == "right": + ops = (operator.gt, operator.le) + else: + raise ValueError( + f"'inclusive' values can be 'both', 'left', 'right', or 'neither' " + f"got {inclusive}" + ) + + g_left = ( + ops[0](data, left) + if left is not None + else np.full(data.shape, True, dtype=bool) + ) + l_right = ( + ops[1](data, right) + if right is not None + else np.full(data.shape, True, dtype=bool) + ) + return np.where(g_left & l_right, props, "")