如何将Pandas混淆矩阵转为Bokeh热力图?修改示例代码生成空图
用Pandas DataFrame绘制Bokeh热力图(以混淆矩阵为例)
我之前调试Bokeh热力图时也踩过这个空白图的坑!尤其是用混淆矩阵这种宽格式DataFrame的时候,官方示例用的是提前整理好的长格式数据,直接套代码肯定出问题,我给你整理一套能跑通的方案:
1. 先把宽格式混淆矩阵转成长格式
Bokeh的热力图需要明确的x分类、y分类、对应值三个字段,而我们的混淆矩阵是宽格式(行是真实类别,列是预测类别,单元格是数量),必须先转成长格式:
import pandas as pd # 先定义示例混淆矩阵(替换成你的真实数据) confusion_matrix = pd.DataFrame( [[80, 10, 5], [5, 90, 5], [3, 7, 90]], index=["真实类别A", "真实类别B", "真实类别C"], columns=["预测类别A", "预测类别B", "预测类别C"] ) # 转成长格式:保留真实类别作为y轴,预测类别作为x轴,数量作为值 df_long = confusion_matrix.reset_index().melt( id_vars="index", var_name="预测类别", value_name="数量" ) df_long = df_long.rename(columns={"index": "真实类别"})
2. 完整的热力图绘制代码
转好数据后,就可以按照Bokeh的规范绘图了,这里我加了hover提示和颜色条,方便查看数据:
from bokeh.plotting import figure, show, output_notebook from bokeh.transform import linear_cmap from bokeh.palettes import Viridis256 from bokeh.models import ColorBar, ColumnDataSource # 如果是在Jupyter里运行就用这个,脚本的话换成output_file("heatmap.html") output_notebook() # 把处理好的长格式数据转成Bokeh数据源 source = ColumnDataSource(df_long) # 获取x和y轴的分类标签(要和数据里的完全一致) y_categories = confusion_matrix.index.tolist() x_categories = confusion_matrix.columns.tolist() # 创建绘图对象 p = figure( x_range=x_categories, y_range=y_categories, title="混淆矩阵热力图", x_axis_label="预测类别", y_axis_label="真实类别", toolbar_location=None, # 隐藏工具栏,不需要可以删掉 tools="hover", tooltips=[("真实类别", "@真实类别"), ("预测类别", "@预测类别"), ("数量", "@数量")] ) # 绘制热力图的矩形块 p.rect( x="预测类别", y="真实类别", width=1, height=1, source=source, # 用颜色映射对应数量值 fill_color=linear_cmap( field_name="数量", palette=Viridis256, low=df_long["数量"].min(), high=df_long["数量"].max() ), line_color="white" # 加白色边框区分每个块 ) # 添加右侧的颜色条 color_bar = ColorBar( color_mapper=linear_cmap( field_name="数量", palette=Viridis256, low=df_long["数量"].min(), high=df_long["数量"].max() ).transform, label_standoff=12, location=(0, 0) ) p.add_layout(color_bar, 'right') # 显示图表 show(p)
3. 为什么你之前会得到空白图?(常见坑)
- 数据格式不匹配:直接用宽格式DataFrame时,Bokeh无法自动识别x、y、值的对应关系,必须转成长格式。
- 分类标签不一致:
x_range和y_range里的标签必须和数据中的完全一致(比如大小写、空格、特殊字符),不然Bokeh找不到对应坐标,就会显示空白。 - 数据源设置错误:建议统一用
ColumnDataSource包裹数据,直接传原始DataFrame容易出现隐式转换错误。
内容的提问来源于stack exchange,提问作者serv-inc
相关产品推荐
相关产品推荐

