在Seaborn FacetGrid中使用map_dataframe绘制热力图报错排查
问题解决:Seaborn热力图FacetGrid报错
ValueError: could not convert string to float 错误原因
- 参数笔误:原代码中
FacetGrid的col='colrow'是错误的,你的数据中不存在colrow列,应改为col='colnum'。 - 数据结构不匹配:
sns.heatmap需要纯数值矩阵作为输入,但直接使用map_dataframe(sns.heatmap)会把包含字符串列(如Hosp、Spec)的整个子DataFrame传递过去,导致无法将字符串转为浮点数的错误。
修正后的完整代码
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt import numpy as np waitremap = {'0-2':0,'3-4':1,'5-6':2,'7-8':3,'9-10':4,'11-12':5} df = pd.DataFrame({ 'Spec':['A','A','A','B','B','B','A','B'], 'Wait':[5,6,2,4,1,2,11,12], 'Hosp':['X1','X2','X1','X2','X1','X2','X1','X2'], 'WaitClass':['5-6','5-6','0-2','3-4','0-2','0-2','11-12','11-12'], }) df = df.assign(waitindex = df.WaitClass.map(waitremap)) # 生成按index归一化的热力图数据 heatdf = (pd.crosstab( index=[df.Hosp,df.Spec], columns=df.WaitClass, values=df.Wait, aggfunc='count', normalize='index' ).assign(colnum =1).reset_index()) # 生成全局归一化的热力图数据 heatdf1 = (pd.crosstab( index=[df.Hosp,df.Spec], columns=df.WaitClass, values=df.Wait, aggfunc='count', normalize=True ).assign(colnum =2).reset_index()) finalheatdf = pd.concat([heatdf,heatdf1]) # 自定义绘图函数:提取数值矩阵并绘制热力图 def plot_heatmap(data, x_cols, ax=None): # 提取指定数值列转为矩阵 heat_data = data[x_cols].values # 获取y轴标签 y_labels = data['Hosp'].tolist() sns.heatmap( heat_data, ax=ax, annot=True, # 显示单元格数值 cmap='YlGnBu', yticklabels=y_labels, xticklabels=x_cols ) ax.set_ylabel('Hosp') ax.set_xlabel('WaitClass') # 指定热力图的x轴列顺序 x_cols = ['0-2','11-12','3-4','5-6'] # 初始化FacetGrid:按colnum分栏,Spec分行 g3 = sns.FacetGrid(finalheatdf, col='colnum', row='Spec', sharex=False, sharey=False) # 映射自定义绘图函数,传递x轴列参数 g3.map_dataframe(plot_heatmap, x_cols=x_cols) # 调整子图间距,避免标签重叠 plt.tight_layout() plt.show()
关键修改说明
- 修正
FacetGrid的col参数为colnum,匹配数据中的分栏字段。 - 自定义
plot_heatmap函数,从子DataFrame中仅提取需要的数值列作为热力图数据源,过滤掉非数值列。 - 设置
sharex=False, sharey=False,让每个子图的坐标轴独立显示,避免标签重叠。 - 添加
annot=True显示热力图单元格内的数值,提升可读性。
内容的提问来源于stack exchange,提问作者sxs
相关产品推荐
相关产品推荐

