You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Plotly热图中排除指定列参与着色并保留列内容展示

如何在Plotly热图中排除指定列参与着色并保留列内容展示

嘿,这个需求我之前做项目的时候刚好遇到过!要实现「保留total列内容展示,但不让它影响热图颜色映射」的效果,我们可以通过「分离着色数据和展示文本+自定义特殊列样式」的方式来搞定,具体步骤和代码如下:

核心思路

Plotly的px.imshow默认会用所有传入的数值计算色阶,所以我们要把数据拆成两部分:

  1. 着色用的核心数据:去掉total列,只用来计算热图的颜色范围
  2. 完整的展示文本:包含total列的所有数值,保证内容不丢失
    然后通过把total列对应的着色值设为NaN(让Plotly忽略它的色阶计算),再给total列的单元格加个中性色背景,和着色区域做区分。

修改后的完整代码

import numpy as np
import pandas as pd
import plotly.express as px

# 生成模拟数据(和你提供的代码一致)
city_origin = ['London', 'Tokio', 'Seoul', 'Paris', 'Tashkent', 'Washington', 'Moscow']
city_current = ['London', 'Madrid', 'Tashkent', 'Seoul', 'Paris', 'Toronto', 'Washington', 'Istanbul', 'Hanoi', 'Manilla', 'Delhi', 'Busan', 'Moscow']
migrant_origin = np.random.choice(city_origin,size = 1000)
migrant_current = np.random.choice(city_current, size = 1000)
migrant_salary = np.random.randint(1300, 6900, size = 1000)
df = pd.DataFrame({'migrant_origin':migrant_origin, 'migrant_current':migrant_current, 'migrant_salary':migrant_salary})

# 生成透视表(和你提供的代码一致)
new_df = pd.pivot_table(df, index = 'migrant_origin', columns = 'migrant_current', values ='migrant_salary', aggfunc = 'sum', fill_value = 0)
new_df['total'] = new_df.sum(axis = 1)
cols = ['total'] + [col for col in new_df.columns if col != 'total']
new_df = new_df[cols]

# -------------------------- 关键修改部分 --------------------------
# 1. 分离出用于计算颜色的核心数据(去掉total列)
color_df = new_df.drop('total', axis=1)
# 2. 构建着色用的z矩阵:给total列对应的位置填充NaN,让Plotly不计算它的颜色
# 因为total列是第一列,所以在z矩阵最前面加一列NaN
z_matrix = np.hstack([np.full((color_df.shape[0], 1), np.nan), color_df.values])
# 3. 准备完整的文本矩阵(包含total列的所有数值)
text_matrix = new_df.values

# 4. 生成热图
fig = px.imshow(
    z_matrix,
    x=new_df.columns,  # 保留完整的列名(包含total)
    y=new_df.index,
    text=text_matrix,  # 显示所有列的数值
    text_auto=True,
    # 强制色阶范围只基于核心着色数据,彻底避免NaN影响
    zmin=color_df.values.min(),
    zmax=color_df.values.max(),
    color_continuous_scale='Blues'  # 可以换成你喜欢的配色
)

# 5. 给total列的单元格加中性色背景,和着色区域区分开
for row_idx in range(len(new_df.index)):
    fig.add_shape(
        type='rect',
        # total列在x轴的第一个位置,所以x范围是-0.5到0.5
        x0=-0.5, x1=0.5,
        # 对应行的y轴范围
        y0=row_idx - 0.5, y1=row_idx + 0.5,
        fillcolor='#f5f5f5',  # 浅灰色,可根据需求调整
        line_width=0,  # 去掉边框
        layer='below'  # 把背景放在文本下方,避免遮挡文字
    )

# 6. 自定义鼠标悬停提示,显示更清晰的信息
fig.update_traces(
    hovertemplate='<b>Origin City:</b> %{y}<br><b>Current City/Total:</b> %{x}<br><b>Total Salary:</b> %{text}<extra></extra>'
)

# 7. 调整布局,让图表更美观
fig.update_layout(
    coloraxis_colorbar=dict(title='Total Salary'),
    xaxis_title='Current City / Total',
    yaxis_title='Origin City',
    margin=dict(l=100, r=20, t=20, b=100)  # 调整边距避免标签被截断
)

fig.show()

效果说明

  • total列的数值会正常显示,但单元格是统一的浅灰色,完全不跟着色区域的色阶变化
  • 热图的颜色只由其他列的数值决定,彻底不受total列的影响
  • 鼠标悬停时能看到完整的信息,体验和正常热图一致

如果你更习惯用plotly.graph_objects做精细控制,也可以用类似思路:把total列的z值设为NaN,再自定义文本和样式。另外如果担心NaN的显示问题,也可以把total列的z值设为远低于核心数据最小值的数,再把色阶zmin设为核心数据的最小值,但这种方法如果核心数据本身有接近最小值的数值会混淆,所以还是用NaN+自定义背景的方法最稳妥。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.07 10:28:02