@@ -1769,6 +1769,68 @@ def highlight_range(
1769
1769
stop = stop ,
1770
1770
)
1771
1771
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
+
1772
1834
@classmethod
1773
1835
def from_custom_template (cls , searchpath , name ):
1774
1836
"""
@@ -1893,8 +1955,32 @@ def _highlight_func(
1893
1955
in_l = data >= l if l is not None else np .full_like (data , True , dtype = bool )
1894
1956
in_h = data <= h if h is not None else np .full_like (data , True , dtype = bool )
1895
1957
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 , "" )
1896
1980
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
+ )
1898
1984
1899
1985
1900
1986
class _Tooltips :
0 commit comments