如何用Python迭代实现多ID的DataFrame重叠子图绘制?
迭代绘制多ID的双数据源重叠子图
核心思路
先提取两个DataFrame中所有唯一的id,根据ID数量动态生成子图布局,然后循环每个ID,统一执行数据筛选、绘图、样式设置的逻辑,彻底避免重复编写子图代码。
完整实现代码
import pandas as pd import matplotlib.pyplot as plt # ---------------------- # 示例数据(可替换为你的真实数据) # ---------------------- df_1 = pd.DataFrame({ 'id': [1,1,2,2,3,3,4,4], 'cycle': [1,2,1,2,1,2,1,2], 'Salary': [5000, 5500, 6000, 6200, 7000, 7500, 8000, 8300] }) df_2 = pd.DataFrame({ 'id': [1,1,2,2,3,3,4,4], 'cycle': [1,2,1,2,1,2,1,2], 'Salary': [4800, 5300, 5900, 6100, 6800, 7300, 7800, 8100] }) # ---------------------- # 核心绘图逻辑 # ---------------------- # 获取所有唯一ID(两个DF结构一致,取任意一个即可) unique_ids = df_1['id'].unique() total_ids = len(unique_ids) # 设置子图布局:2列,自动计算行数 cols = 2 rows = (total_ids + cols - 1) // cols # 向上取整计算行数 # 创建画布和子图集合 fig, axes = plt.subplots(rows, cols, figsize=(14, 10)) axes = axes.flatten() # 将多维子图数组转为一维,方便循环遍历 # 循环每个ID绘制子图 for idx, current_id in enumerate(unique_ids): # 筛选当前ID的两组数据 df1_filtered = df_1[df_1['id'] == current_id] df2_filtered = df_2[df_2['id'] == current_id] # 获取当前子图对象 ax = axes[idx] # 绘制两条重叠曲线 ax.plot(df1_filtered['cycle'], df1_filtered['Salary'], marker='o', color='#1f77b4', linewidth=2, label='df_1') ax.plot(df2_filtered['cycle'], df2_filtered['Salary'], marker='s', color='#ff7f0e', linewidth=2, label='df_2') # 设置子图样式 ax.set_title(f'ID: {current_id}', fontsize=12, fontweight='bold') ax.set_xlabel('Cycle', fontsize=10) ax.set_ylabel('Salary', fontsize=10) ax.legend() ax.grid(True, alpha=0.3, linestyle='--') # 隐藏多余的空白子图(当ID数量不是列数的整数倍时) for ax in axes[total_ids:]: ax.axis('off') # 自动调整子图间距,避免标签重叠 plt.tight_layout() plt.show()
优化扩展:封装绘图函数
如果需要多次复用绘图逻辑,可以把单ID的绘图代码封装成独立函数,让主代码更简洁:
def plot_salary_by_id(ax, df_a, df_b, target_id): """ 在指定子图上绘制单个ID的双数据源Salary曲线 :param ax: 子图对象 :param df_a: 第一个DataFrame :param df_b: 第二个DataFrame :param target_id: 要绘制的ID值 """ df_a_sub = df_a[df_a['id'] == target_id] df_b_sub = df_b[df_b['id'] == target_id] ax.plot(df_a_sub['cycle'], df_a_sub['Salary'], marker='o', color='#1f77b4', linewidth=2, label='df_1') ax.plot(df_b_sub['cycle'], df_b_sub['Salary'], marker='s', color='#ff7f0e', linewidth=2, label='df_2') ax.set_title(f'ID: {target_id}', fontsize=12, fontweight='bold') ax.set_xlabel('Cycle', fontsize=10) ax.set_ylabel('Salary', fontsize=10) ax.legend() ax.grid(True, alpha=0.3, linestyle='--')
调用时只需在循环中执行:
for idx, current_id in enumerate(unique_ids): plot_salary_by_id(axes[idx], df_1, df_2, current_id)
内容的提问来源于stack exchange,提问作者NN_Developer
相关产品推荐
相关产品推荐

