Python Seaborn:使用非对称自定义错误条按组制作条形图
我有一个Pandas数据框架,它有两个组列,如下所示Python Seaborn:使用非对称自定义错误条按组制作条形图,python,matplotlib,plot,data-visualization,seaborn,Python,Matplotlib,Plot,Data Visualization,Seaborn,我有一个Pandas数据框架,它有两个组列,如下所示 gr1 grp2 variables lb m ub A A1 V1 1.00 1.50 2.5 A A2 V2 1.50 2.50 3.5 B A1 V1 3.50 14.50 30.5 B A2 V2 0.25 0.75 1
gr1 grp2 variables lb m ub
A A1 V1 1.00 1.50 2.5
A A2 V2 1.50 2.50 3.5
B A1 V1 3.50 14.50 30.5
B A2 V2 0.25 0.75 1.0
我正在尝试使用FacetGrid
为variables
中的每个变量获取一个单独的子条形图。我正在努力构建我需要的最终情节,如下图所示
这就是我目前所拥有的
g = sns.FacetGrid(df, col="variables", hue="grp1")
g.map(sns.barplot, 'grp2', 'm', order=times)
但不幸的是,这正在堆积我所有的数据点
我应该如何使用Seaborn
更新:下面的代码主要是我想要的,但目前没有显示yerr
g = sns.factorplot(x="Grp2", y="m", hue="Grp1", col="variables", data=df, kind="bar", size=4, aspect=.7, sharey=False)
如何将
lb
和ub
合并为factorplot上的错误条?在开始之前,让我提到matplotlib要求错误与数据相关,而不是绝对边界。因此,我们将修改dataframe,通过减去相应的列来说明这一点
u = u"""grp1 grp2 variables lb m ub
A A1 V1 1.00 1.50 2.5
A A2 V2 1.50 2.50 3.5
B A1 V1 7.50 14.50 20.5
B A2 V2 0.25 0.75 1.0
A A2 V1 1.00 6.50 8.5
A A1 V2 1.50 3.50 6.5
B A2 V1 3.50 4.50 15.5
B A1 V2 8.25 12.75 13.9"""
import io
import pandas as pd
df = pd.read_csv(io.StringIO(u), delim_whitespace=True)
# errors must be relative to data (not absolute bounds)
df["lb"] = df["m"]-df["lb"]
df["ub"] = df["ub"]-df["m"]
现在有两种基本相同的解决方案。让我们从一个解决方案开始,该解决方案不使用seaborn,而是使用pandas plotting包装器(原因将在稍后明确)
不使用Seaborn
Pandas允许使用数据帧绘制分组条形图,其中每列属于或构成一个组。
因此,应采取的步骤是:
变量的数量创建多个子批次
groupby
dateframe byvariables
grp1
的值作为列,而m
的值作为值。对两个错误列执行相同的操作import io
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv(io.StringIO(u), delim_whitespace=True)
# errors must be relative to data (not absolute bounds)
df["lb"] = df["m"]-df["lb"]
df["ub"] = df["ub"]-df["m"]
def func(x,y,h,lb,ub, **kwargs):
data = kwargs.pop("data")
# from https://stackoverflow.com/a/37139647/4124317
errLo = data.pivot(index=x, columns=h, values=lb)
errHi = data.pivot(index=x, columns=h, values=ub)
err = []
for col in errLo:
err.append([errLo[col].values, errHi[col].values])
err = np.abs(err)
p = data.pivot(index=x, columns=h, values=y)
p.plot(kind='bar',yerr=err,ax=plt.gca(), **kwargs)
fig, axes = plt.subplots(ncols=len(df.variables.unique()))
for ax, (name, group) in zip(axes,df.groupby("variables")):
plt.sca(ax)
func("grp2", "m", "grp1", "lb", "ub", data=group, color=["limegreen", "indigo"])
plt.title(name)
plt.show()
使用Seaborn
Seaborn FactoryPlot不允许自定义错误栏。因此,需要使用FaceGrid
方法。为了不让条形图堆叠,可以将hue
参数放在map
调用中。因此,以下内容相当于问题的sns.factorplot
调用
g = sns.FacetGrid(data=df, col="variables", size=4, aspect=.7 )
g.map(sns.barplot, "grp2", "m", "grp1", order=["A1","A2"] )
现在的问题是,我们无法从外部将ErrorBar输入条形图,或者更重要的是,我们无法将分组条形图的错误提供给seaborn.barplot
。对于未分组的条形图,可以通过yerr
参数提供错误,该参数传递到matplotlibplt.bar
绘图。这一概念如所示。但是,由于seaborn.barplot
多次调用plt.bar
,每个hue
调用一次,因此每次调用中的错误都是相同的(或者它们的维度不匹配)
因此,我看到的唯一选择是使用FacetGrid
,并将上面使用的函数完全映射到它。这在某种程度上使seaborn的使用变得过时,但为了完整起见,这里是FaceGrid
解决方案
import io
import numpy as np
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
df = pd.read_csv(io.StringIO(u), delim_whitespace=True)
# errors must be relative to data (not absolute bounds)
df["lb"] = df["m"]-df["lb"]
df["ub"] = df["ub"]-df["m"]
def func(x,y,h,lb,ub, **kwargs):
data = kwargs.pop("data")
# from https://stackoverflow.com/a/37139647/4124317
errLo = data.pivot(index=x, columns=h, values=lb)
errHi = data.pivot(index=x, columns=h, values=ub)
err = []
for col in errLo:
err.append([errLo[col].values, errHi[col].values])
err = np.abs(err)
p = data.pivot(index=x, columns=h, values=y)
p.plot(kind='bar',yerr=err,ax=plt.gca(), **kwargs)
g = sns.FacetGrid(df, col="variables", size=4, aspect=.7, )
g.map_dataframe(func, "grp2", "m", "grp1", "lb", "ub" , color=["limegreen", "indigo"])
g.add_legend()
plt.show()
非常感谢您的详细回复,我对代码做了一些修改,使其适合我的具体用例,并且工作得非常完美。