使用Seaborn在单张图像中整合展示多特征分组散点图的实现方法
核心实现思路
由于不同特征的取值范围差异较大,直接将所有特征的数值放在同一y轴会导致小范围特征的点被压缩失真,最适配当前需求的方案是构建共享x轴的纵向对齐子图组:所有子图横向对齐,x轴统一为患者维度刻度,每个子图单独对应一个特征、独立适配自身的y轴范围。最终出来的效果就是横向对齐的映射式视图:每个患者在x轴上的位置完全固定,所有特征的散点都在对应患者的垂直对齐位置上,既保证视觉统一性,又不会因为量纲差异损失数据可读性。
具体实现步骤
方案一:轻量化手动建图(无需修改原数据结构)
直接基于Matplotlib创建共享x轴的垂直子图组,逐个子图映射原有单特征绘图逻辑,完全匹配当前的宽表格式,不需要额外做数据转换:
- 导入依赖库,定义需要纳入绘图的特征列表
- 创建和特征数量一致的垂直排列子图,开启
sharex=True保证所有子图的患者刻度位置完全对齐 - 遍历每个特征,在对应子图上运行原有的
stripplot绘图逻辑
完整代码:
import matplotlib.pyplot as plt import seaborn as sns # 配置全局绘图风格 sns.set_style("whitegrid") # 定义需要整合展示的特征列表 target_features = ["Feature1", "Feature2", "Feature3"] # 创建共享x轴的垂直子图组 fig, axes = plt.subplots( nrows=len(target_features), ncols=1, sharex=True, figsize=(6, 2.5 * len(target_features)) # 画布高度随特征数量自动适配 ) # 逐个子图绘制对应特征的散点 for ax, feat in zip(axes, target_features): sns.stripplot( y=feat, x="Patient", data=features, ax=ax, jitter=True, size=6, alpha=0.7 ) # 自动调整子图间距,避免标签重叠 plt.tight_layout() plt.show()
方案二:分面网格实现(适合需要扩展自定义样式的场景)
如果后续需要增加颜色映射、自定义排列顺序等扩展功能,可以先将宽表转换为长表格式,再用Seaborn的FacetGrid实现分面:
- 用
melt方法将宽表转为长格式,新增列记录特征名称和对应数值 - 基于特征列创建纵向分面网格,共享x轴
- 将
stripplot映射到每个分面单元格中
转换长表的代码:
long_features = features.melt( id_vars=["Patient", "Visit"], var_name="Feature", value_name="Value" )
分面绘图代码:
g = sns.FacetGrid( long_features, row="Feature", row_order=target_features, sharex=True, height=2.5, aspect=3 ) g.map( sns.stripplot, "Patient", "Value", jitter=True, size=6, alpha=0.7 ) g.fig.tight_layout() plt.show()
可选优化方向
- 若需要区分不同就诊次数(Visit)的散点,可在
stripplot的参数中增加hue="Visit",再通过plt.legend()添加统一图例 - 若特征数量较少、画布为宽屏,可将垂直子图改为横向排列(设置
ncols=len(target_features), nrows=1, sharey=False),适配宽屏展示 - 由于每个子图独立适配y轴范围,不需要手动对特征做归一化处理,可完整保留各特征的原始分布特征
内容的提问来源于stack exchange,提问作者FiReTiTi
相关产品推荐
相关产品推荐

