【问题标题】:Plot Shaded Error Bars from Pandas Agg从 Pandas Agg 绘制阴影误差条
【发布时间】:2018-11-10 16:15:45
【问题描述】:

我有以下格式的数据:

|      | Measurement 1 |      | Measurement 2 |      |
|------|---------------|------|---------------|------|
|      | Mean          | Std  | Mean          | Std  |
| Time |               |      |               |      |
| 0    | 17            | 1.10 | 21            | 1.33 |
| 1    | 16            | 1.08 | 21            | 1.34 |
| 2    | 14            | 0.87 | 21            | 1.35 |
| 3    | 11            | 0.86 | 21            | 1.33 |

我正在使用以下代码从这些数据中生成一个 matplotlib 折线图,它将标准偏差显示为填充区域,如下所示:

def seconds_to_minutes(x, pos):
    minutes = f'{round(x/60, 0)}'
    return minutes

fig, ax = plt.subplots()
mean_temperature_over_time['Measurement 1']['mean'].plot(kind='line', yerr=mean_temperature_over_time['Measurement 1']['std'], alpha=0.15, ax=ax)
mean_temperature_over_time['Measurement 2']['mean'].plot(kind='line', yerr=mean_temperature_over_time['Measurement 2']['std'], alpha=0.15, ax=ax)

ax.set(title="A Line Graph with Shaded Error Regions", xlabel="x", ylabel="y")
formatter = FuncFormatter(seconds_to_minutes)
ax.xaxis.set_major_formatter(formatter)
ax.grid()
ax.legend(['Mean 1', 'Mean 2'])

输出:

这似乎是一个非常混乱的解决方案,并且实际上只产生阴影输出,因为我有这么多数据。从带有阴影错误区域的数据框中生成折线图的正确方法是什么?我看过Plot yerr/xerr as shaded region rather than error bars,但无法根据我的情况调整它。

【问题讨论】:

    标签: python-3.x pandas matplotlib jupyter-notebook


    【解决方案1】:

    链接的解决方案有什么问题?看起来很简单。

    请允许我重新排列您的数据集,以便更轻松地加载到 Pandas DataFrame

       Time  Measurement  Mean   Std
    0     0            1    17  1.10
    1     1            1    16  1.08
    2     2            1    14  0.87
    3     3            1    11  0.86
    4     0            2    21  1.33
    5     1            2    21  1.34
    6     2            2    21  1.35
    7     3            2    21  1.33
    


    for i, m in df.groupby("Measurement"):
        ax.plot(m.Time, m.Mean)
        ax.fill_between(m.Time, m.Mean - m.Std, m.Mean + m.Std, alpha=0.35)
    

    这是一些随机生成的数据的结果:

    编辑

    由于问题显然是在迭代您的特定数据帧格式,让我展示您如何做到这一点(我是 pandas 的新手,所以可能有更好的方法)。如果我正确理解了您的屏幕截图,您应该有类似的内容:

    Measurement    1          2      
                Mean   Std Mean   Std
    Time                             
    0             17  1.10   21  1.33
    1             16  1.08   21  1.34
    2             14  0.87   21  1.35
    3             11  0.86   21  1.33
    
    df.info()
    <class 'pandas.core.frame.DataFrame'>
    Int64Index: 4 entries, 0 to 3
    Data columns (total 4 columns):
    (1, Mean)    4 non-null int64
    (1, Std)     4 non-null float64
    (2, Mean)    4 non-null int64
    (2, Std)     4 non-null float64
    dtypes: float64(2), int64(2)
    memory usage: 160.0 bytes
    
    df.columns
    MultiIndex(levels=[[1, 2], [u'Mean', u'Std']],
               labels=[[0, 0, 1, 1], [0, 1, 0, 1]],
               names=[u'Measurement', None])
    

    您应该能够对其进行迭代并获得相同的绘图:

    for i, m in df.groupby("Measurement"):
        ax.plot(m["Time"], m['Mean'])
        ax.fill_between(m["Time"],
                        m['Mean'] - m['Std'],
                        m['Mean'] + m['Std'], alpha=0.35)
    

    或者您可以将其重新堆叠为上述格式

    (df.stack("Measurement")      # stack "Measurement" columns row by row
     .reset_index()               # make "Time" a normal column, add a new index
     .sort_values("Measurement")  # group values from the same Measurement
     .reset_index(drop=True))     # drop sorted index and make a new one
    

    【讨论】:

    • 啊,问题是数据集是 pandas .groupby.agg 方法的结果,我不知道如何将它从该结构中获取到您用来生成的那个我想要的图表。
    • 您能以这种格式发布数据集的样本吗?就像print(df) 打印出来的一样
    • @LarsaSolidor 您可以使用mean_temperature_over_time.swaplevel(0,1,axis=1).stack().reset_index().sort_values("Measurement") 获得我的格式,或者您可以使用for i, m in mean_temperature_over_time.groupby(level=0, axis=1): print(m[i].Mean) 之类的内容在您的数据框中进行迭代
    • @LarsaSolidor 更新了答案,请查看编辑
    • @LarsaSolidor 用一种更容易掌握的方法更新了答案(无需手动级别寻址和交换)。串联 pandas 函数的诀窍是从第一个函数开始,看看它如何重塑数据框并逐个添加所有步骤以更好地了解发生了什么
    猜你喜欢
    • 1970-01-01
    • 2011-02-25
    • 2010-11-16
    • 1970-01-01
    • 2012-02-16
    • 2012-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多