ENH: tablewise Styler.background_gradient #15204 (#21259) · pandas-dev/pandas@bdb6168 (original) (raw)

`@@ -913,21 +913,22 @@ def background_gradient(self, cmap='PuBu', low=0, high=0, axis=0,

`

913

913

`def _background_gradient(s, cmap='PuBu', low=0, high=0,

`

914

914

`text_color_threshold=0.408):

`

915

915

`"""Color background in a range according to the data."""

`

``

916

`+

if (not isinstance(text_color_threshold, (float, int)) or

`

``

917

`+

not 0 <= text_color_threshold <= 1):

`

``

918

`` +

msg = "text_color_threshold must be a value from 0 to 1."

``

``

919

`+

raise ValueError(msg)

`

``

920

+

916

921

`with _mpl(Styler.background_gradient) as (plt, colors):

`

917

``

`-

rng = s.max() - s.min()

`

``

922

`+

smin = s.values.min()

`

``

923

`+

smax = s.values.max()

`

``

924

`+

rng = smax - smin

`

918

925

`# extend lower / upper bounds, compresses color range

`

919

``

`-

norm = colors.Normalize(s.min() - (rng * low),

`

920

``

`-

s.max() + (rng * high))

`

921

``

`-

matplotlib modifies inplace?

`

``

926

`+

norm = colors.Normalize(smin - (rng * low), smax + (rng * high))

`

``

927

`+

matplotlib colors.Normalize modifies inplace?

`

922

928

`# https://github.com/matplotlib/matplotlib/issues/5427

`

923

``

`-

normed = norm(s.values)

`

924

``

`-

c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]

`

925

``

`-

if (not isinstance(text_color_threshold, (float, int)) or

`

926

``

`-

not 0 <= text_color_threshold <= 1):

`

927

``

`` -

msg = "text_color_threshold must be a value from 0 to 1."

``

928

``

`-

raise ValueError(msg)

`

``

929

`+

rgbas = plt.cm.get_cmap(cmap)(norm(s.values))

`

929

930

``

930

``

`-

def relative_luminance(color):

`

``

931

`+

def relative_luminance(rgba):

`

931

932

`"""

`

932

933

` Calculate relative luminance of a color.

`

933

934

``

`@@ -936,25 +937,33 @@ def relative_luminance(color):

`

936

937

``

937

938

` Parameters

`

938

939

` ----------

`

939

``

`-

color : matplotlib color

`

940

``

`-

Hex code, rgb-tuple, or HTML color name.

`

``

940

`+

color : rgb or rgba tuple

`

941

941

``

942

942

` Returns

`

943

943

` -------

`

944

944

` float

`

945

945

` The relative luminance as a value from 0 to 1

`

946

946

` """

`

947

``

`-

rgb = colors.colorConverter.to_rgba_array(color)[:, :3]

`

948

``

`-

rgb = np.where(rgb <= .03928, rgb / 12.92,

`

949

``

`-

((rgb + .055) / 1.055) ** 2.4)

`

950

``

`-

lum = rgb.dot([.2126, .7152, .0722])

`

951

``

`-

return lum.item()

`

952

``

-

953

``

`-

text_colors = ['#f1f1f1' if relative_luminance(x) <

`

954

``

`-

text_color_threshold else '#000000' for x in c]

`

955

``

-

956

``

`-

return ['background-color: {color};color: {tc}'.format(

`

957

``

`-

color=color, tc=tc) for color, tc in zip(c, text_colors)]

`

``

947

`+

r, g, b = (

`

``

948

`+

x / 12.92 if x <= 0.03928 else ((x + 0.055) / 1.055 ** 2.4)

`

``

949

`+

for x in rgba[:3]

`

``

950

`+

)

`

``

951

`+

return 0.2126 * r + 0.7152 * g + 0.0722 * b

`

``

952

+

``

953

`+

def css(rgba):

`

``

954

`+

dark = relative_luminance(rgba) < text_color_threshold

`

``

955

`+

text_color = '#f1f1f1' if dark else '#000000'

`

``

956

`+

return 'background-color: {b};color: {c};'.format(

`

``

957

`+

b=colors.rgb2hex(rgba), c=text_color

`

``

958

`+

)

`

``

959

+

``

960

`+

if s.ndim == 1:

`

``

961

`+

return [css(rgba) for rgba in rgbas]

`

``

962

`+

else:

`

``

963

`+

return pd.DataFrame(

`

``

964

`+

[[css(rgba) for rgba in row] for row in rgbas],

`

``

965

`+

index=s.index, columns=s.columns

`

``

966

`+

)

`

958

967

``

959

968

`def set_properties(self, subset=None, **kwargs):

`

960

969

`"""

`