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
`"""
`