繁体   English   中英

Seaborn:使用不对称的自定义误差条按组制作条形图

[英]Seaborn: Making barplot by group with asymmetrical custom error bars

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

我试图让一个独立的子barplot为每个变量variables使用FacetGrid 我正在努力建立我需要的最终情节,如下所示。

使用FacetGrid和多个分类变量进行绘图

这就是我到目前为止所拥有的。

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作为误差条并入factorplot?

在我们开始之前,让我提一下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的解决方案开始,但是大熊猫绘图包装器(原因将在后面变得清晰)。

不使用Seaborn

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

  1. 根据不同variables的数量创建多个子图。
  2. groupby由dateframe variables
  3. 对于每个组,创建一个透视数据框,其值为grp1作为列, m为值。 对两个错误列执行相同操作。
  4. 应用如何将不对称错误栏添加到Pandas分组条形图中的解决方案

然后代码看起来像:

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 factorplot不允许自定义错误栏。 因此,人们需要使用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图。 这个概念在这个问题中显示出来。 然而,由于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()

在此输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM