gpt4 book ai didi

python - 使用不对称的自定义误差线按组制作seaborn.barplot

转载 作者:行者123 更新时间:2023-11-30 22:31:13 25 4
gpt4 key购买 nike

我有一个 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.0

我正在尝试使用FacetGridvariables中的每个变量获取单独的子条形图。我正在尝试构建我需要的最终图,如下所示。

Plot with FacetGrid and Multiple Categorical 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)

如何将 lbub 合并为因子图上的误差线?

最佳答案

在我们开始之前,我要提一下,matplotlib 要求误差是相对于数据的,而不是绝对边界。因此,我们将修改数据框以通过减去相应的列来解释这一点。

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绘图包装器的解决方案开始(稍后会清楚原因)。

不使用 Seaborn

Pandas 允许使用每列属于或构成一组的数据框来绘制分组条形图。因此要采取的步骤是

  1. 根据不同变量的数量创建多个子图。
  2. groupby变量分组的日期框
  3. 为每个组创建一个透视数据框,其中将 grp1 的值作为列,将 m 的值作为值。对两个错误列执行相同的操作。
  4. 应用 How add asymmetric errorbars to Pandas grouped barplot? 中的解决方案

代码将如下所示:

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()

enter image description here

使用Seaborn

Seaborn 因子图不允许自定义误差条。因此,需要使用 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"] )

现在的问题是,我们无法从外部将错误栏放入条形图中,或更重要的是,我们无法将分组条形图的错误提供给 seaborn.barplot。对于非分组条形图,可以通过 yerr 参数提供错误,该参数被传递到 matplotlib plt.bar 图中。这个概念显示在this question中。 。但是,由于 seaborn.barplot 多次调用 plt.bar,每个 hue 调用一次,因此每次调用中的错误将是相同的(或它们的尺寸不匹配)。

因此,我看到的唯一选择是使用 FacetGrid 并将与上面使用的函数完全相同的映射到它。这在某种程度上使得seaborn的使用变得过时,但为了完整起见,这里是FacetGrid解决方案。

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()

enter image description here

关于python - 使用不对称的自定义误差线按组制作seaborn.barplot,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45875143/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com