如何高效重塑DataFrame字典以绘制小提琴图
如何高效重塑DataFrame字典以绘制小提琴图
嘿,你的思路完全没问题,不过确实可以借助pandas的原生功能来简化这个数据重塑的过程,不用写那么多层嵌套循环,代码会更简洁也更易维护,处理大数据时效率也更高。
第一步:先把所有数据整合到一个大DataFrame里
我们可以先把字典里的所有DataFrame合并,同时保留元组键里的第一个标识(我们叫它section),这样后续处理会方便很多:
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 初始化列表存放处理后的子DataFrame df_list = [] for (section, _), df in data_dict.items(): # 只保留我们关心的两列,同时添加section列标记来源 temp_df = df[['Data_1', 'Data_4']].copy() temp_df['section'] = section df_list.append(temp_df) # 合并成一个完整的DataFrame combined_df = pd.concat(df_list, ignore_index=True)
这样combined_df就把所有数据整合到了一起,包含Data_1、Data_4和section三列,不用再手动拼接列表。
第二步:快速生成你需要的new_dict(可选)
如果还是想要和原来结构一致的new_dict,可以用字典推导结合groupby实现,一行就能搞定:
new_dict = { col: pd.concat( [group[col].reset_index(drop=True) for _, group in combined_df.groupby('section')], axis=1, keys=[5,7] ) for col in ['Data_1', 'Data_4'] }
这个逻辑是:对每个目标列,按section分组提取数据,重置索引后横向拼接成DataFrame,列名对应section的数值。
第三步:绘图可以更简洁(无需new_dict)
其实有了combined_df之后,甚至不用生成new_dict,直接提取数据绘图就行,代码更短:
for col in ['Data_1', 'Data_4']: fig, ax = plt.subplots() # 按section分组提取对应列的数据,组成绘图所需的列表 plot_data = [combined_df[combined_df['section'] == s][col].values for s in [5,7]] ax.violinplot(plot_data, showmeans=True) ax.set(title=col, xlabel='Section', ylabel='Value') ax.set_xticks(np.arange(1,3), labels=['5','7']) plt.show()
如果愿意用seaborn的话,代码会更省心,还能自动处理分组:
import seaborn as sns # 把数据转成长格式,适配seaborn的绘图逻辑 melted_df = combined_df.melt(id_vars='section', var_name='Data_Type', value_name='Value') # 按Data_Type分图,绘制小提琴图 g = sns.FacetGrid(melted_df, col='Data_Type', sharey=True) g.map(sns.violinplot, 'section', 'Value', showmeans=True) g.set_axis_labels('Section', 'Value') g.set_titles(col_template='{col_name}') plt.show()
这个方法的优势
- 代码更简洁,减少嵌套循环,可读性更高
- 利用pandas的向量化操作,处理你说的大尺度数据(索引到3000、多列)时,速度会比手动循环快很多
- 后续如果要新增列或section,只需要修改对应的列表,不用调整循环逻辑
备注:内容来源于stack exchange,提问作者Regina Phalange
相关产品推荐
相关产品推荐

