如何调整DataFrame格式以适配sns.violinplot()绘制分组小提琴图?
问题描述
我想用sns.violinplot()绘制按两个变量分组的垂直小提琴图,效果对应seaborn官方文档里的第三个示例图。当前我的DataFrame每行对应一名研究参与者,列包含不同脑区的结果数据以及患者/对照组标识,但没法把数据调整成合适格式,实现患者组和对照组的小提琴图并排展示。我试过unstack()、stack()这些方法,都没成功。示例DataFrame如下:
nm_rt_vta_sn_m nm_lt_vta_sn_m nm_lt_sn_post_m nm_rt_sn_post_m patient 0 0.17 0.20 0.22 0.19 1 1 0.19 0.20 0.23 0.22 1 2 0.22 0.21 0.23 0.24 1 3 0.19 0.19 0.21 0.21 1 4 0.23 0.24 0.25 0.25 1 140 0.22 0.23 0.27 0.24 0 141 0.21 0.21 0.22 0.23 0 142 0.19 0.22 0.24 0.21 0 143 0.21 0.23 0.25 0.22 0 144 0.20 0.21 0.24 0.22 0
解决方案
核心问题是当前DataFrame为宽格式,而seaborn分类绘图函数需要长格式数据。用pandas.melt()即可完成转换,步骤如下:
1. 转换数据格式
使用melt将多个脑区列合并为一个分类列,对应数值单独成列,保留patient作为分组依据:
import pandas as pd import seaborn as sns import matplotlib.pyplot as plt # 假设你的DataFrame名为df df_melted = df.melt( id_vars='patient', # 保留的分组标识列 var_name='脑区', # 新的分类列名称 value_name='结果' # 数值列名称 )
转换后的数据结构示例:
| patient | 脑区 | 结果 |
|---|---|---|
| 1 | nm_rt_vta_sn_m | 0.17 |
| 1 | nm_lt_vta_sn_m | 0.20 |
| ... | ... | ... |
| 0 | nm_rt_sn_post_m | 0.22 |
2. 绘制小提琴图
用转换后的长格式数据,指定x为脑区、y为结果、hue为患者分组,设置split=False让两组小提琴并排展示:
sns.set_theme(style="whitegrid") plt.figure(figsize=(12, 6)) sns.violinplot( x='脑区', y='结果', hue='patient', data=df_melted, split=False, # 关闭拆分,实现两组并排 inner='quartile', # 显示四分位数线 palette='muted' ) plt.title('不同脑区的患者/对照组结果对比') plt.xlabel('脑区') plt.ylabel('结果数值') plt.legend(title='分组', labels=['对照组', '患者组']) plt.show()
关键说明
melt是宽转长的标准方法,比stack()更直观,可直接定义新列名称和保留分组列。hue参数区分患者/对照组,split=False确保两组小提琴各自独立并排,对应官方第三个示例的展示效果。
内容的提问来源于stack exchange,提问作者Luke Vano
相关产品推荐
相关产品推荐

