4. Python医疗可视化核心库入门
在医疗数据分析项目中,可视化库的选择往往决定了后续开发效率与交付形态。Python 生态中主流的四个可视化库——Matplotlib、Seaborn、Plotly、Bokeh——并非互相替代关系,而是分别覆盖“底层控制、统计快捷、交互探索、Web 部署”四类需求。理解它们的定位差异,比记住某个 API 更重要。
四个库的定位差异
Matplotlib 是 Python 可视化的底层基础设施。它提供 Figure(画布)与 Axes(坐标区)两级对象模型,几乎所有其他库都构建在它之上或可导出到它的对象。它的优势是控制粒度极细:可以精确指定每个刻度、每条误差线、每个子图的位置。在医疗场景中,需要绘制带置信区间的生存曲线、自定义标注的 ROC 曲线、多面板对照图时,Matplotlib 是可靠选择。代价是代码相对冗长,统计图形需要手工计算。
Seaborn 建立在 Matplotlib 之上,面向统计图形。它直接接受 pandas DataFrame,用 hue、col、row 等参数自动完成分组着色与分面,内置箱线图、小提琴图、回归图、热力图等。医疗数据中常见的“按科室分组的住院天数分布”“按分期分面的生存概率”用 Seaborn 几行即可完成。它的短板是交互能力弱,输出仍是静态图。
Plotly 是交互式可视化库,输出基于 JavaScript 的 HTML 图表,支持缩放、悬停提示、图例点击筛选。在医疗场景中,适合做患者指标的时间序列探索、多指标联动筛选、地理分布展示。Plotly Express 提供高层接口,px.line、px.scatter 等函数可直接接受 DataFrame。它也能导出静态图片,但需要额外安装 kaleido。
Bokeh 同样面向浏览器交互,但更强调“用 Python 构建可部署的 Web 应用”。它提供 ColumnDataSource 数据源与回调机制,适合把可视化嵌入到医疗看板、随访系统中。相比 Plotly,Bokeh 在自定义交互逻辑和流式数据更新上更灵活,但学习曲线略陡。
医疗数据上的基本绘图流程
无论使用哪个库,医疗数据绘图都遵循一条共同主线:数据准备 → 图形对象构建 → 视觉映射 → 输出。区别在于各库对这条主线的封装程度不同。
以一份模拟的住院患者数据为例,字段包括 patient_id、department(科室)、los_days(住院天数)、age、readmitted(是否再入院)。数据准备阶段需要确认:缺失值如何处理、分类字段的类别顺序、数值字段的量纲。医疗数据中住院天数常呈右偏分布,直接画直方图会挤在左侧,通常先做对数变换或改用箱线图。
Matplotlib 的典型流程是显式创建画布与坐标区:
import matplotlib.pyplot as plt
import pandas as pd
df = pd.read_csv("patients_demo.csv")
fig, ax = plt.subplots(figsize=(8, 5))
for dept, group in df.groupby("department"):
ax.hist(group["los_days"], bins=20, alpha=0.5, label=dept)
ax.set_xlabel("住院天数")
ax.set_ylabel("患者人数")
ax.set_title("各科室住院天数分布")
ax.legend()
fig.savefig("los_by_dept.png", dpi=150, bbox_inches="tight")
Seaborn 把分组与统计合并到一行:
import seaborn as sns
sns.set_theme(style="whitegrid")
g = sns.displot(data=df, x="los_days", hue="department",
col="readmitted", kind="kde", fill=True)
g.savefig("los_kde.png", dpi=150)
Plotly 的交互版本:
import plotly.express as px
fig = px.box(df, x="department", y="los_days",
color="readmitted", points="outliers",
title="各科室住院天数箱线图")
fig.write_html("los_box.html")
fig.write_image("los_box.png", width=900, height=500)
Bokeh 适合把图嵌入可交互页面,核心是 ColumnDataSource:
from bokeh.plotting import figure, output_file, save
from bokeh.models import ColumnDataSource
source = ColumnDataSource(df)
p = figure(title="年龄与住院天数", x_axis_label="年龄",
y_axis_label="住院天数", width=700, height=450)
p.circle("age", "los_days", source=source, alpha=0.4,
color="#3b82f6", legend_label="患者")
output_file("age_los.html")
save(p)
输出格式与选择依据
输出格式直接影响交付方式。静态图片常用 PNG(位图,适合报告、论文插图,dpi 建议 150~300)与 SVG/PDF(矢量,适合期刊排版,缩放不失真)。Matplotlib 与 Seaborn 通过 savefig 直接输出这些格式。Plotly 与 Bokeh 的原生输出是 HTML,适合浏览器查看与分享;若需静态图,Plotly 依赖 kaleido,Bokeh 可借助 selenium 导出 PNG。
选择库时可以按三个问题判断:第一,图形是否需要读者交互?需要则优先 Plotly 或 Bokeh。第二,是否要嵌入已有 Web 系统并自定义回调?是则 Bokeh 更合适。第三,是否以统计分组和分面为主?是则 Seaborn 效率最高。若以上都不突出,或需要极细的图形控制,回到 Matplotlib。