You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何基于Pandas按多列分组绘制可变数量的子图与曲线

如何基于Pandas按多列分组绘制可变数量的子图与曲线

我接触Python已经好几个月了,但偶尔还是会被一些小问题难住 😅 这次想请教一下怎么用Matplotlib从按两列分组的DataFrame里绘制子图,或者有没有相关的方法思路可以参考?

先给你看看我用到的DataFrame示例:

nameNcoeffX1Y1
0F2F2_1100.56451
1F2F2_1500.45005
2F2F2_21250.53641
3F2F2_25250.53641
4F2F2_31550.45067
5F2F2_35550.38828
6F2F2_41850.33279
7F2F2_45850.35315
8F2F2_51950.2756
9F2F2_55950.32571
10F2F2_611200.159
11F2F2_651200.27583
12F2F2_711500.05648
13F2F2_751500.21128
14F3F3_1100.42757
15F3F3_1500.32409
16F3F3_21250.36033
17F3F3_25250.2701
18F3F3_31550.2161
19F3F3_35550.17014
20F3F3_41850.08191
21F3F3_45850.10512
22F3F3_51950.04468
23F3F3_55950.09686
24F3F3_611200.07025
25F3F3_651200.033
26F3F3_711500.10689
27F3F3_751500.01334

我现在是按namecoeff这两列分组,想要实现的效果是:每个name对应一个子图,每个子图里再绘制不同coeff对应的曲线(比如示例里F2F3各占一个子图,每个子图里有coeff=1coeff=5两条曲线)。之前按单列分组绘图没什么问题,但多列分组的逻辑我就有点绕不过来了,麻烦帮忙解答下~


别担心,我来一步步给你拆解这个需求,其实多列分组绘图的核心就是先按一级分组(比如name)来生成子图,再在每个子图里遍历二级分组(比如coeff)来画曲线,具体可以这么做:

步骤1:导入需要的库

首先得把Pandas和Matplotlib导入进来:

import pandas as pd
import matplotlib.pyplot as plt

步骤2:准备你的DataFrame(这里用你给的示例数据)

先把示例数据转成DataFrame,当然你也可以直接用自己的数据源:

data = [
    ["F2", "F2_1", 1, 0, 0.56451],
    ["F2", "F2_1", 5, 0, 0.45005],
    ["F2", "F2_2", 1, 25, 0.53641],
    ["F2", "F2_2", 5, 25, 0.53641],
    ["F2", "F2_3", 1, 55, 0.45067],
    ["F2", "F2_3", 5, 55, 0.38828],
    ["F2", "F2_4", 1, 85, 0.33279],
    ["F2", "F2_4", 5, 85, 0.35315],
    ["F2", "F2_5", 1, 95, 0.2756],
    ["F2", "F2_5", 5, 95, 0.32571],
    ["F2", "F2_6", 1, 120, 0.159],
    ["F2", "F2_6", 5, 120, 0.27583],
    ["F2", "F2_7", 1, 150, 0.05648],
    ["F2", "F2_7", 5, 150, 0.21128],
    ["F3", "F3_1", 1, 0, 0.42757],
    ["F3", "F3_1", 5, 0, 0.32409],
    ["F3", "F3_2", 1, 25, 0.36033],
    ["F3", "F3_2", 5, 25, 0.2701],
    ["F3", "F3_3", 1, 55, 0.2161],
    ["F3", "F3_3", 5, 55, 0.17014],
    ["F3", "F3_4", 1, 85, 0.08191],
    ["F3", "F3_4", 5, 85, 0.10512],
    ["F3", "F3_5", 1, 95, 0.04468],
    ["F3", "F3_5", 5, 95, 0.09686],
    ["F3", "F3_6", 1, 120, 0.07025],
    ["F3", "F3_6", 5, 120, 0.033],
    ["F3", "F3_7", 1, 150, 0.10689],
    ["F3", "F3_7", 5, 150, 0.01334],
]
df = pd.DataFrame(data, columns=["name", "N", "coeff", "X1", "Y1"])

步骤3:按多列分组并绘制子图

这里的思路是:

  1. 先获取所有唯一的name值,确定子图的数量
  2. 创建对应的子图布局
  3. 遍历每个name,在对应的子图里,再按coeff分组,绘制每条曲线
  4. 加上图例、标题这些美化元素,让图更清晰

具体代码如下:

# 获取所有唯一的name,确定子图数量
unique_names = df["name"].unique()
num_plots = len(unique_names)

# 创建子图布局,这里用1行多列,你也可以根据数量调整成多行
fig, axes = plt.subplots(nrows=1, ncols=num_plots, figsize=(12, 5), sharey=True)

# 如果只有一个子图,axes会是单个对象,需要转成列表统一处理
if num_plots == 1:
    axes = [axes]

# 遍历每个name和对应的子图
for ax, name in zip(axes, unique_names):
    # 筛选当前name的数据
    name_data = df[df["name"] == name]
    # 按coeff分组,绘制每条曲线
    for coeff, group in name_data.groupby("coeff"):
        # 绘制X1 vs Y1的曲线,这里可以根据你的需求调整x和y列
        ax.plot(group["X1"], group["Y1"], marker='o', label=f'coeff={coeff}')
    # 设置子图标题
    ax.set_title(f'Name: {name}')
    # 设置坐标轴标签
    ax.set_xlabel('X1')
    ax.set_ylabel('Y1')
    # 添加图例
    ax.legend()

# 调整子图间距,避免重叠
plt.tight_layout()
# 显示图形
plt.show()

代码小解释

  • 首先通过df["name"].unique()拿到所有要画的子图主题,这样不管你有多少个name,子图数量都会自动适配,不用手动改代码
  • plt.subplots创建子图时,sharey=True可以让所有子图的Y轴刻度一致,方便不同name的数据对比
  • 嵌套循环是核心:外层循环处理每个name对应的子图,内层循环在子图里按coeff分组,把每个分组的数据绘制成一条带标记点的曲线
  • 最后用tight_layout()自动调整布局,避免标签和标题重叠,让图看起来更清爽

这样运行代码后,就能得到你想要的效果:每个name一个子图,每个子图里有不同coeff的曲线啦~

备注:内容来源于stack exchange,提问作者Nakira

火山引擎 最新活动