如何在Plotly热图中排除指定列参与着色并保留列内容展示
如何在Plotly热图中排除指定列参与着色并保留列内容展示
嘿,这个需求我之前做项目的时候刚好遇到过!要实现「保留total列内容展示,但不让它影响热图颜色映射」的效果,我们可以通过「分离着色数据和展示文本+自定义特殊列样式」的方式来搞定,具体步骤和代码如下:
核心思路
Plotly的px.imshow默认会用所有传入的数值计算色阶,所以我们要把数据拆成两部分:
- 着色用的核心数据:去掉total列,只用来计算热图的颜色范围
- 完整的展示文本:包含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
相关产品推荐
相关产品推荐

