Python Matplotlib 在具有置信区间的条形图中绘制样本均值,但看起来像箱线图

Python Matplotlib plotting sample means in bar chart with confidence intervals but looks like box plots

我想将四个时间序列的均值绘制到具有置信区间的 Matplotlib 条形图中。我还想给它们上不同的颜色,生成这样的条形图

所以我写了下面的代码:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(12345)
df = pd.DataFrame([np.random.normal(-10, 200, 100), 
                   np.random.normal(42, 150, 100), 
                   np.random.normal(0, 120, 100), 
                   np.random.normal(-5, 57, 100)], 
                  index=[2012, 2013, 2014, 2015])
years = ('2012', '2013', '2014', '2015')
y_pos = np.arange(len(years))
df1_mean = df.iloc[0].mean()
df1_std = df.iloc[0].std()
df2_mean = df.iloc[1].mean()
df2_std = df.iloc[1].std()
df3_mean = df.iloc[2].mean()
df3_std = df.iloc[2].std()
df4_mean = df.iloc[3].mean()
df4_std = df.iloc[3].std()

value = (df1_mean, df2_mean, df3_mean, df4_mean)
Std = (df1_std, df2_std, df3_std, df4_std)

plt.bar(y_pos, value, yerr=Std, align='center', alpha=0.5)
plt.xticks(y_pos, years)
plt.ylabel('Stock price')
plt.title('Something')
plt.show()

这给了我这个(见上文)。不完全是我所期待的。此外,它看起来像一个箱形图而不是条形图,其中每个样本均值应该一直向下到 x 轴。

我承认我是 Matplotlib 的新手,但我真的很想知道我的代码发生了什么。这应该是一个简单的任务,但我似乎无法完成。我应该改为调用 .subplots() 命令吗? 最重要的是,如果有人愿意告诉我如何 (1) 在同一条形图上的 x 轴上(例如,在值 100 上)添加一条水平线作为阈值,我将不胜感激, 以及 (2) 为这四个条设置不同的颜色(选择的确切颜色并不重要)?

谢谢。

默认情况下,由 plt.bar 创建的柱状图从 y=0 开始。对于正值,它们向上扩展,对于负值,它们向下扩展。
您可以使用 bottom 参数让它们以不同的值开始,并将 bottom 的数量添加到值中。这是在下面的代码中完成的,我还将数据框置于更常见的形状中(年份是列)。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(12345)
df = pd.DataFrame(np.c_[np.random.normal(-10,200,100), 
                   np.random.normal(42,150,100), 
                   np.random.normal(0,120,100), 
                   np.random.normal(-5,57,100)], 
                  columns=[2012,2013,2014,2015])

value = df.mean()
std = df.std()

colors=["red", "green", "blue", "purple"]
plt.axhline(y=100, zorder=0)
plt.bar(range(len(df.columns)), value+np.abs(df.values.min()), bottom=df.values.min(), 
        yerr=std, align='center', alpha=0.5, color=colors)

plt.xticks(range(len(df.columns)), df.columns)
plt.ylabel('Stock price')
plt.title('Something')
plt.show()

您正在寻找置信区间,但 .std() 没有这样做。在将它传递给 yerr 之前,您需要将它除以人口规模的平方根,然后乘以 95% 的 z 分数,即 1.96。如果这样做,您将不需要调整条形的底部。我认为您实际上需要做的不止于此,例如找到间隔的上限和下限,但现在我们已经达到了我的知识极限,所以我会先停下来。

试试这个:

    xvals = range(len(df))
    yvals = df.mean(axis = 1).values
    y_std = df_transp.std()/np.sqrt(df_transp.shape[0])*1.96
    plt.bar(xvals, yvals, yerr=y_std, width = 0.5, capsize=15)