【问题标题】:Add error bars with customized upper and lower bounds to a bar plot in python将具有自定义上限和下限的误差线添加到python中的条形图中
【发布时间】:2020-12-31 18:46:52
【问题描述】:

我想将我计算的 HDI(高密度区间)(下面 df 中的列 hdi_bothhdi_onelower_upper)添加到条形图中。

但是,我无法弄清楚如何添加误差线/CI,以便每个误差线都有一个自定义的上下界,它们独立于 y 值(在本例中为 proportion_correct 中的对应值)。

例如,Exp.的 HDI 间隔。 1 与guesses_correct both 的下限为0.000000 ,上限为0.130435proportion_correct 0.000000

我看到的所有选项都包括指定相对于 y 轴上的值的上限和下限,这不是我想要的。

任何帮助将不胜感激。

谢谢,

阿亚拉

import os
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

df = pd.DataFrame({
 'exp': ['Exp. 1', 'Exp. 1', 'Exp. 2', 'Exp. 2', 'Exp. 3', 'Exp. 3', 'Exp. 4', 'Exp. 4', 'Exp. 5', 'Exp. 5',
 'Collapsed', 'Collapsed'],
 'proportion_correct': [0.0, 0.304347826, 0.058823529000000006, 0.31372549, 0.047619048, 0.333333333, 0.12244898, 0.428571429, 0.12244898, 0.367346939, 0.082901554, 0.35751295299999997],
 'guesses_correct': ['both', 'one', 'both', 'one', 'both', 'one', 'both', 'one', 'both', 'one', 'both', 'one'],
 'hdi_both': [0.0, 0.130434783, 0.0, 0.078431373, 0.0, 0.1, 0.0, 0.08, 0.0, 0.081632653, 0.005181347, 0.051813472],
 'hdi_one': [0.130434783, 0.47826087, 0.156862745, 0.41176470600000004, 0.1, 0.5, 0.16, 0.4, 0.163265306, 0.408163265, 0.21761658, 0.341968912],
 'lower_upper': ['lower', 'upper', 'lower', 'upper', 'lower', 'upper', 'lower', 'upper', 'lower', 'upper', 'lower', 'upper']
})

print(df.head())
Out[4]: 
      exp  proportion_correct guesses_correct  hdi_both   hdi_one lower_upper
0  Exp. 1            0.000000            both  0.000000  0.130435       lower
1  Exp. 1            0.304348             one  0.130435  0.478261       upper
2  Exp. 2            0.058824            both  0.000000  0.156863       lower
3  Exp. 2            0.313725             one  0.078431  0.411765       upper
4  Exp. 3            0.047619            both  0.000000  0.100000       lower
# Make bar plot
sns.barplot(x='exp',
            y='proportion_correct',
            hue='guesses_correct',
            data=df)

plt.ylim([0, 0.5])
plt.xlabel('Experiment')
plt.ylabel('Proportion Correct')
plt.legend(title='Correct guesses', loc='upper right')
plt.axhline(y=0.277777, color='dimgray', linestyle='--')
plt.annotate(' chance\n one', (5.5, 0.27))
plt.axhline(y=0.02777, color='dimgray', linestyle='--')
plt.annotate(' chance\n both', (5.5, 0.02))
# Show the plot
plt.show()

这是我要为其添加 HDI 的条形图

【问题讨论】:

    标签: python pandas matplotlib seaborn errorbar


    【解决方案1】:

    我最终将垂直线绘制为误差线。这是我的代码,以防它对某人有所帮助。

    df = pd.DataFrame({'exp': ['Exp. 1', 'Exp. 1', 'Exp. 2', 'Exp. 2', 'Exp. 3', 'Exp. 3', 'Exp. 4', 'Exp. 4', 'Exp. 5', 'Exp. 5', 'Collapsed', 'Collapsed'],
                       'proportion_correct': [0.0, 0.304347826, 0.058823529000000006, 0.31372549, 0.047619048, 0.333333333, 0.12244898, 0.428571429, 0.12244898, 0.367346939, 0.082901554, 0.35751295299999997],
                       'guesses_correct': ['both', 'one', 'both', 'one', 'both', 'one', 'both', 'one', 'both', 'one', 'both', 'one'], 
                       'hdi_low': [0.0, 0.130434783, 0.0, 0.156862745, 0.0, 0.1, 0.0, 0.16, 0.0, 0.163265306, 0.005181347, 0.21761658],
                       'hdi_high': [0.130434783, 0.47826087, 0.078431373, 0.41176470600000004, 0.1, 0.5, 0.08, 0.4, 0.081632653, 0.408163265, 0.051813472, 0.341968912]
                      })
    df.head()
    Out[4]: 
      exp  proportion_correct guesses_correct   hdi_low  hdi_high
    0  Exp. 1            0.000000            both  0.000000  0.130435
    1  Exp. 1            0.304348             one  0.130435  0.478261
    2  Exp. 2            0.058824            both  0.000000  0.078431
    3  Exp. 2            0.313725             one  0.156863  0.411765
    4  Exp. 3            0.047619            both  0.000000  0.100000
    

    以下axvlinesaxhlines 函数取自How to draw vertical lines on a given plot in matplotlib。为了清楚起见,我不在这里写它们。

        # Make bar plot
        x_col = 'exp'
        y_col = 'proportion_correct'
        hue_col = 'guesses_correct'
        low_col = 'hdi_low'
        high_col = 'hdi_high'
        plot = sns.barplot(x=x_col,
                    y=y_col,
                    hue=hue_col,
                    data=df)
        plt.ylim([0, 0.55])
        plt.yticks([0, 0.1, 0.2, 0.3, 0.4, 0.5], [0, 0.1, 0.2, 0.3, 0.4, 0.5])
        plt.xlabel('Experiment')
        plt.ylabel('Proportion Correct')
        plt.legend(title='Correct guesses', loc='upper right')
        plt.axhline(y=0.277777, color='dimgray', linestyle='--')
        plt.annotate(' chance\n one', (5.65, 0.27))
        plt.axhline(y=0.02777, color='dimgray', linestyle='--')
        plt.annotate(' chance\n both', (5.65, 0.02))
        lims_x = list(map(lambda x, y: (x, y), df[low_col].to_list(), df[high_col].to_list()))
        xss = [-0.2, 0.2, 0.8, 1.2, 1.8, 2.2, 2.8, 3.2, 3.8, 4.2, 4.8, 5.2]
        yss = [i for sub in lims_x for i in sub]
        lims_y = [(-0.3, -0.1), (-0.3, -0.1), (0.1, 0.3), (0.1, 0.3), (0.7, 0.9), (0.7, 0.9), (1.1, 1.3), (1.1, 1.3),
                  (1.7, 1.9), (1.7, 1.9), (2.1, 2.3), (2.1, 2.3), (2.7, 2.9), (2.7, 2.9), (3.1, 3.3),  (3.1, 3.3),
                  (3.7, 3.9), (3.7, 3.9), (4.1, 4.3), (4.1, 4.3), (4.7, 4.9), (4.7, 4.9), (5.1, 5.3), (5.1, 5.3)]
        for xs, lim in zip(xss, lims_x):
            plot = axvlines(xs, lims=lim, color='black')
        for yx, lim in zip(yss, lims_y):
            plot = axhlines(yx, lims=lim, color='black')
        plt.show()
    

    这就是剧情

    【讨论】:

      【解决方案2】:

      尽管您已经以绝对值计算了误差条的下限和上限,但它们通常被认为是围绕特定 y 值的下限和上限误差。但是很容易通过从您计算的范围中减去 y 值来计算误差线的“相对”长度。

      然后您可以使用plt.errorbar() 进行绘图。请注意,要使用此函数,所有错误值都必须为正数。

      由于您使用hue= 拆分,您必须遍历hue 的不同级别,并考虑条形的移位(默认为-0.2 和+0.2 两个级别的色调):

      # Make bar plot
      x_col = 'exp'
      y_col = 'proportion_correct'
      hue_col = 'guesses_correct'
      low_col = 'hdi_both'
      high_col = 'hdi_one'
      sns.barplot(x=x_col,
                  y=y_col,
                  hue=hue_col,
                  data=df)
      
      for (h,g),pos in zip(df.groupby(hue_col),[-0.2,0.2]):
          err = g[[low_col, high_col]].subtract(g[y_col], axis=0).abs().T.values
          x = np.arange(len(g[x_col].unique()))+pos
          plt.errorbar(x=x, y=g[y_col], yerr=err, fmt='none', capsize=5, ecolor='k')
      

      【讨论】:

      • 嗨@Diziet Asahi,我认为在计算误差线时存在一些错误,因此它们将对应于误差线的绝对值。例如在 Exp。 4、proportion_correctboth0.12244898的上下界分别为00.08。但是,从您生成的图表看来,下限是0,这是正确的,但图表中的上限是~0.18,这是不正确的。图表中的其他误差线也是如此。因此,您的代码中的某些内容对我来说看起来不正确,但我仍在尝试理解是什么。谢谢!
      • 我想我误解了你的数据框的格式。我的印象是Exp. 4both 的边界是[0.000000,0.160000](同一行上的值)。但是您是说它们应该是[0.000000,0.080000]hdi_both 列中连续两行中的值)?
      • 如果您自己根据一些原始数据创建了这个数据框,那么(至少在我看来)让每一行对应一个条件(Exp. N,both/one,@ 987654342@,hdi_low,hdi_high),与该条件相关的所有值(包括配置区间界限)在同一行。
      • 嗨@Diziet Asahi。我试过了,但它仍然没有正确显示错误栏。我尝试编辑我的问题以解释原因,但编辑未获批准。
      猜你喜欢
      • 1970-01-01
      • 2023-03-19
      • 2016-01-04
      • 2014-11-18
      • 1970-01-01
      • 1970-01-01
      • 2014-05-24
      • 2020-12-31
      • 1970-01-01
      相关资源
      最近更新 更多