Python Matplotlib 在条形图中绘制样本均值,具有置信区间,但看起来像箱形图
Posted
技术标签:
【中文标题】Python Matplotlib 在条形图中绘制样本均值,具有置信区间,但看起来像箱形图【英文标题】:Python Matplotlib plotting sample means in bar chart with confidence intervals but looks like box plots 【发布时间】:2017-08-18 09:19:06 【问题描述】:我想将四个时间序列的均值绘制成带有置信区间的 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) 这四个条的颜色不同(选择的确切颜色并不重要)?
谢谢。
【问题讨论】:
将条形扩展到图表底部似乎很随意。那么,您希望条形高度表示什么?当将某物与零进行比较有意义时,通常会制作条形图。如果这不是您需要的,也许您应该考虑其他情节类型,例如箱线图。 我希望条形高度代表样本均值,其中 95% 置信区间环绕条形顶部。 在接受的答案中,每个条形顶部的 y 坐标代表样本均值,条形高度代表“该样本均值比所有数据的历史最小值高多少"。 【参考方案1】:默认情况下,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()
【讨论】:
我确实做到了。再次感谢。 我要补充一点,使用 bar 的capsize
属性来获取标准行顶部的横杆。要让条相互接触,请将条宽设置为 1.0
嘿!感谢这个精彩的解释,但是我们如何在错误栏的末端添加垂直条(所以它看起来像两个倒置的 T)?【参考方案2】:
您正在寻找置信区间,但 .std() 没有这样做。在将其传递给 yerr 之前,您需要将其除以人口规模的 sqrt 并乘以 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)
【讨论】:
以上是关于Python Matplotlib 在条形图中绘制样本均值,具有置信区间,但看起来像箱形图的主要内容,如果未能解决你的问题,请参考以下文章
如何在 matplotlib pandas 的一张图中组合两个文件的两个条形图
Python Matplotlib – 在 x 轴上代表采样位置的条形图
如何在 matplotlib 条形图中用希腊符号替换主轴和次轴的图例标签?