Skip to content

Commit e6f7758

Browse files
committed
ENH: Allow elementwise coloring in background_gradient with axis=None #15204
1 parent bc9241d commit e6f7758

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

doc/source/whatsnew/v0.24.0.txt

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ Other Enhancements
1414
^^^^^^^^^^^^^^^^^^
1515
- :func:`to_datetime` now supports the ``%Z`` and ``%z`` directive when passed into ``format`` (:issue:`13486`)
1616
- :func:`to_csv` now supports ``compression`` keyword when a file handle is passed. (:issue:`21227`)
17+
- Allow elementwise coloring in ``style.background_gradient`` with ``axis=None`` (:issue:`15204`)
18+
-
1719
-
1820

1921
.. _whatsnew_0240.api_breaking:

pandas/io/formats/style.py

+13-8
Original file line numberDiff line numberDiff line change
@@ -901,16 +901,21 @@ def background_gradient(self, cmap='PuBu', low=0, high=0, axis=0,
901901
def _background_gradient(s, cmap='PuBu', low=0, high=0):
902902
"""Color background in a range according to the data."""
903903
with _mpl(Styler.background_gradient) as (plt, colors):
904-
rng = s.max() - s.min()
904+
smin = s.values.min()
905+
smax = s.values.max()
906+
rng = smax - smin
905907
# extend lower / upper bounds, compresses color range
906-
norm = colors.Normalize(s.min() - (rng * low),
907-
s.max() + (rng * high))
908-
# matplotlib modifies inplace?
908+
norm = colors.Normalize(smin - (rng * low), smax + (rng * high))
909+
# matplotlib colors.Normalize modifies inplace?
909910
# https://github.com/matplotlib/matplotlib/issues/5427
910-
normed = norm(s.values)
911-
c = [colors.rgb2hex(x) for x in plt.cm.get_cmap(cmap)(normed)]
912-
return ['background-color: {color}'.format(color=color)
913-
for color in c]
911+
rgbs = plt.cm.get_cmap(cmap)(norm(s.values))
912+
913+
css = lambda x: 'background-color: {c}'.format(c=colors.rgb2hex(x))
914+
if s.ndim == 1:
915+
return [css(x) for x in rgbs]
916+
else:
917+
return pd.DataFrame([[css(x) for x in row] for row in rgbs],
918+
index=s.index, columns=s.columns)
914919

915920
def set_properties(self, subset=None, **kwargs):
916921
"""

pandas/tests/io/formats/test_style.py

+29
Original file line numberDiff line numberDiff line change
@@ -1033,6 +1033,35 @@ def test_background_gradient(self):
10331033
subset=pd.IndexSlice[1, 'A'])._compute().ctx
10341034
assert result[(1, 0)] == ['background-color: #fff7fb']
10351035

1036+
@td.skip_if_no_mpl
1037+
def test_background_gradient_axis(self):
1038+
df = pd.DataFrame([[1, 2], [2, 4]], columns=['A', 'B'])
1039+
1040+
low = ['background-color: #f7fbff']
1041+
high = ['background-color: #08306b']
1042+
mid = ['background-color: #abd0e6']
1043+
result = df.style.background_gradient(cmap='Blues',
1044+
axis=0)._compute().ctx
1045+
assert result[(0, 0)] == low
1046+
assert result[(0, 1)] == low
1047+
assert result[(1, 0)] == high
1048+
assert result[(1, 1)] == high
1049+
1050+
result = df.style.background_gradient(cmap='Blues',
1051+
axis=1)._compute().ctx
1052+
assert result[(0, 0)] == low
1053+
assert result[(0, 1)] == high
1054+
assert result[(1, 0)] == low
1055+
assert result[(1, 1)] == high
1056+
1057+
result = df.style.background_gradient(cmap='Blues',
1058+
axis=None)._compute().ctx
1059+
assert result[(0, 0)] == low
1060+
assert result[(0, 1)] == mid
1061+
assert result[(1, 0)] == mid
1062+
assert result[(1, 1)] == high
1063+
1064+
10361065

10371066
def test_block_names():
10381067
# catch accidental removal of a block

0 commit comments

Comments
 (0)