如何基于单列将数据框着色为在整行中具有相同颜色的条件热图
How to color a dataframe to a conditional heatmap with same color across whole row based on a single column
所以我有一个看起来像这样的数据框:
Target, Achieved, Goal, Remaining
10, 5, 50, 5
4, 5, 125, 0
3, 3, 100, 0
8, 2, 25, 6
我想根据颜色显示带有可见信息的数据框,在此条件下:
- 如果实现了目标,我只想让行显示为绿色,而不管实际超出目标的程度如何。所以整个第二行和第三行将是相同的绿色
- 如果没有达到目标,我想根据热图给它们上色。所以在这里我希望第 4 行比第 1 行更暗(可以说是红色),因为我在该行的目标上遗漏了更多内容。
对于单一颜色,以下功能完美运行:感谢回答
def highlight_col(x):
#copy df to new - original data are not changed
df = x.copy()
#set by condition
mask = df['Goal Completion (%)'] >= 100
df.loc[mask, :] = 'background-color: lightgreen'
df.loc[~mask,:] = 'background-color: pink'
return df
对于不排除目标完成条件的简单热图,可以通过:
df.style.background_gradient(cmap='Reds')
但是它:
- 包括整个数据帧
- 每列分别着色
- 无法排除已实现目标的行
- 无法在我上面的函数中使用(尝试在最后一行使用:
df.loc[~mask,:] = 'background_gradient: Reds'
,但也没有用。
P.S。我的 Dataframe 不是很大,所以我更喜欢 table 从我可以 select 行的地方着色,而不是拥有一个全新的可视化。非常欢迎任何改善情况的建议!
示例输出:
您可以将 cmap
应用于数据帧的特定子集
df.style.background_gradient('Reds', subset=pd.IndexSlice[df.Goal < 100, ])
输出
您可以尝试通过 Goal
中的值提取颜色 cmap
:
def hightlight_col(d, refcol=None, cmap='Reds'):
min_goal, max_goal = d[refcol].agg(['min','max'])
goals = d[refcol].sub(min_goal)/(max_goal-min_goal)
cmap=mpl.cm.get_cmap(cmap)
return pd.DataFrame([[f'background-color: {mpl.colors.to_hex(cmap(goal))}']*d.shape[1]
for goal in goals
], index=d.index, columns=d.columns)
df.style.apply(hightlight_col, refcol='Goal',
cmap='coolwarm', axis=None)
输出:
也许您正在寻找这样的东西(使用@QuangHoang 方法):
import pandas as pd
import numpy as np
import matplotlib as mpl
df = pd.read_clipboard(sep=',\s+')
cmap = mpl.cm.get_cmap('RdYlGn')
norm = mpl.colors.Normalize(df['Goal'].min(), 100.)
def colorRow(s):
return [f'background-color: {mpl.colors.to_hex(cmap(norm(s["Goal"])))}' for _ in s]
df.style.apply(colorRow, axis=1)
输出:
所以我有一个看起来像这样的数据框:
Target, Achieved, Goal, Remaining
10, 5, 50, 5
4, 5, 125, 0
3, 3, 100, 0
8, 2, 25, 6
我想根据颜色显示带有可见信息的数据框,在此条件下:
- 如果实现了目标,我只想让行显示为绿色,而不管实际超出目标的程度如何。所以整个第二行和第三行将是相同的绿色
- 如果没有达到目标,我想根据热图给它们上色。所以在这里我希望第 4 行比第 1 行更暗(可以说是红色),因为我在该行的目标上遗漏了更多内容。
对于单一颜色,以下功能完美运行:感谢回答
def highlight_col(x):
#copy df to new - original data are not changed
df = x.copy()
#set by condition
mask = df['Goal Completion (%)'] >= 100
df.loc[mask, :] = 'background-color: lightgreen'
df.loc[~mask,:] = 'background-color: pink'
return df
对于不排除目标完成条件的简单热图,可以通过:
df.style.background_gradient(cmap='Reds')
但是它:
- 包括整个数据帧
- 每列分别着色
- 无法排除已实现目标的行
- 无法在我上面的函数中使用(尝试在最后一行使用:
df.loc[~mask,:] = 'background_gradient: Reds'
,但也没有用。
P.S。我的 Dataframe 不是很大,所以我更喜欢 table 从我可以 select 行的地方着色,而不是拥有一个全新的可视化。非常欢迎任何改善情况的建议!
示例输出:
您可以将 cmap
应用于数据帧的特定子集
df.style.background_gradient('Reds', subset=pd.IndexSlice[df.Goal < 100, ])
输出
您可以尝试通过 Goal
中的值提取颜色 cmap
:
def hightlight_col(d, refcol=None, cmap='Reds'):
min_goal, max_goal = d[refcol].agg(['min','max'])
goals = d[refcol].sub(min_goal)/(max_goal-min_goal)
cmap=mpl.cm.get_cmap(cmap)
return pd.DataFrame([[f'background-color: {mpl.colors.to_hex(cmap(goal))}']*d.shape[1]
for goal in goals
], index=d.index, columns=d.columns)
df.style.apply(hightlight_col, refcol='Goal',
cmap='coolwarm', axis=None)
输出:
也许您正在寻找这样的东西(使用@QuangHoang 方法):
import pandas as pd
import numpy as np
import matplotlib as mpl
df = pd.read_clipboard(sep=',\s+')
cmap = mpl.cm.get_cmap('RdYlGn')
norm = mpl.colors.Normalize(df['Goal'].min(), 100.)
def colorRow(s):
return [f'background-color: {mpl.colors.to_hex(cmap(norm(s["Goal"])))}' for _ in s]
df.style.apply(colorRow, axis=1)
输出: