如何通过迭代实现多ID多特征的DataFrame重叠子图绘制
用迭代简化多子图绘制的解决方案
你完全可以通过封装重复逻辑+循环迭代的方式替代手动写9次子图代码,核心是把单个子图的绘制逻辑抽成函数,再批量遍历ID和特征来生成所有图。下面是具体实现步骤:
1. 先搞定列名映射(解决两个DF结构不同的问题)
因为两个DF的特征列名不一样,先做个字典把对应特征的列名关联起来,替换成你实际的列名即可:
feature_col_map = { "Salary": {"df1": "salary_col_in_df1", "df2": "salary_col_in_df2"}, "Children": {"df1": "kids_col_in_df1", "df2": "children_col_in_df2"}, "Expenditure": {"df1": "expense_col_in_df1", "df2": "expenditure_col_in_df2"} }
2. 提取所有需要处理的ID
把两个DF里的唯一ID取出来(如果只需要处理共有的ID,就取交集;要全量处理就取并集):
import pandas as pd all_ids = pd.concat([df1['id'], df2['id']]).unique()
3. 封装单个子图的绘制函数
把画一个特征子图的逻辑写成函数,避免重复写冗余代码:
import matplotlib.pyplot as plt def draw_single_subplot(ax, target_id, feature_name, col_map, df_a, df_b): # 筛选当前ID的数据 data_a = df_a[df_a['id'] == target_id] data_b = df_b[df_b['id'] == target_id] # 绘制两个DF的曲线 ax.plot(data_a['cycle'], data_a[col_map['df1']], marker='o', label='DF1') ax.plot(data_b['cycle'], data_b[col_map['df2']], marker='s', label='DF2') # 设置子图样式 ax.set_title(f'ID {target_id}: {feature_name} vs Cycle') ax.set_xlabel('Cycle') ax.set_ylabel(feature_name) ax.legend() ax.grid(alpha=0.3)
4. 循环迭代生成所有子图
用嵌套循环遍历每个ID和每个特征,自动生成对应布局的子图:
for current_id in all_ids: # 每个ID对应1行3列的子图布局,可根据需求调整行列数 fig, subplots = plt.subplots(1, 3, figsize=(18, 5)) # 加个总标题,让图的主题更清晰 plt.suptitle(f'ID {current_id} - Feature vs Cycle Comparison', fontsize=14, y=1.03) # 遍历每个特征,给每个子图传参绘制 for ax, (feat_name, cols) in zip(subplots, feature_col_map.items()): draw_single_subplot(ax, current_id, feat_name, cols, df1, df2) plt.tight_layout() plt.show() # 如果需要批量保存图片,取消下面注释 # plt.savefig(f'id_{current_id}_feature_plots.png', dpi=300, bbox_inches='tight')
这样不管你有多少个ID,都不用手动重复写子图代码——后续要加新特征,只在feature_col_map里加新条目就行;要调整子图样式,只改draw_single_subplot函数里的逻辑。
额外小技巧
- 如果ID数量多,建议把图片批量保存到本地,避免弹窗太多影响操作
- 要是特征数量变化,直接调整
subplots的行列数(比如2行2列)即可 - 想统一所有子图的x轴范围,可以提前计算全局的最小/最大cycle值,在函数里加
ax.set_xlim(min_cycle, max_cycle)
内容的提问来源于stack exchange,提问作者NN_Developer
相关产品推荐
相关产品推荐

