Skip to content

Commit 4ede159

Browse files
committed
quantile add
1 parent 232ba41 commit 4ede159

File tree

1 file changed

+87
-1
lines changed

1 file changed

+87
-1
lines changed

pandas/io/formats/style.py

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1769,6 +1769,68 @@ def highlight_range(
17691769
stop=stop,
17701770
)
17711771

1772+
def highlight_quantile(
1773+
self,
1774+
subset: Optional[IndexLabel] = None,
1775+
color: str = "yellow",
1776+
q_low: float = 0.0,
1777+
q_high: float = 1.0,
1778+
axis: Optional[Axis] = 0,
1779+
props: Optional[str] = None,
1780+
) -> Styler:
1781+
"""
1782+
Highlight values defined by inclusion in given quantile by shading the
1783+
background, or otherwise.
1784+
1785+
Parameters
1786+
----------
1787+
subset : IndexSlice, default None
1788+
A valid slice for ``data`` to limit the style application to.
1789+
color : str, default 'yellow'
1790+
Background color added to CSS style.
1791+
q_low : float, default 0
1792+
Left bound for the target quantile range (exclusive if not 0).
1793+
q_high : float, default 1
1794+
Right bound for the target quantile range (inclusive)
1795+
axis : {0 or 'index', 1 or 'columns', None}, default 0
1796+
Apply to each column (``axis=0`` or ``'index'``), to each row
1797+
(``axis=1`` or ``'columns'``), or to the entire DataFrame at once
1798+
with ``axis=None``.
1799+
props : str, default None
1800+
CSS properties to use for highlighting. If ``props`` is given, ``color``
1801+
is not used.
1802+
1803+
Returns
1804+
-------
1805+
self : Styler
1806+
1807+
See Also
1808+
--------
1809+
Styler.highlight_max:
1810+
Styler.highlight_min:
1811+
Styler.highlight_range:
1812+
1813+
Notes
1814+
-----
1815+
This function only works with consistent ``dtypes`` within the ``subset``.
1816+
For example a mixture of datetime-like and float items will raise errors.
1817+
1818+
This method uses ``pandas.qcut`` to implement the quantile labelling of data
1819+
values.
1820+
"""
1821+
if props is None:
1822+
props = f"background-color: {color};"
1823+
return self.apply(
1824+
_Builtins._highlight_func,
1825+
axis=axis,
1826+
subset=subset,
1827+
props=props,
1828+
highlight="quantile",
1829+
q_low=q_low,
1830+
q_high=q_high,
1831+
axis_=axis,
1832+
)
1833+
17721834
@classmethod
17731835
def from_custom_template(cls, searchpath, name):
17741836
"""
@@ -1893,8 +1955,32 @@ def _highlight_func(
18931955
in_l = data >= l if l is not None else np.full_like(data, True, dtype=bool)
18941956
in_h = data <= h if h is not None else np.full_like(data, True, dtype=bool)
18951957
return np.where(in_l & in_h, props, "")
1958+
elif highlight == "quantile":
1959+
l, h = kwargs.get("q_low"), kwargs.get("q_high")
1960+
if l > 0:
1961+
q, tgt_label = [0, l, h], 1
1962+
else:
1963+
q, tgt_label = [0, h], 0
1964+
# if l > 0 and h < 1:
1965+
# q, tgt_label = [0, l, h, 1], 1
1966+
# elif l > 0 and h == 1:
1967+
# q, tgt_label = [0, l, h], 1
1968+
# elif l == 0 and h < 1:
1969+
# q, tgt_label = [0, h, 1], 0
1970+
# elif l == 0 and h == 1:
1971+
# q, tgt_label = [0, 1], 0
1972+
# else:
1973+
# raise ValueError("'q_low' and 'q_high' must be in range [0,1]")
1974+
if kwargs.get("axis_") is None:
1975+
shape = data.values.shape
1976+
labels = pd.qcut(data.values.ravel(), q=q, labels=False).reshape(shape)
1977+
else:
1978+
labels = pd.qcut(data, q=q, labels=False)
1979+
return np.where(labels == tgt_label, props, "")
18961980
else:
1897-
raise ValueError("'highlight' must be one of 'max', 'min', 'null', 'range'")
1981+
raise ValueError(
1982+
"'highlight' must be one of 'max', 'min', 'null', 'range', 'quantile'."
1983+
)
18981984

18991985

19001986
class _Tooltips:

0 commit comments

Comments
 (0)