代码之家  ›  专栏  ›  技术社区  ›  Black

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

  •  3
  • Black  · 技术社区  · 8 年前

    我有一个熊猫数据框架,它有两个组列,如下所示。

    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
    

    variables 使用 FacetGrid

    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)
    

    lb ub 作为FactoryPlot上的误差线?

    1 回复  |  直到 8 年前
        1
  •  7
  •   ImportanceOfBeingErnest    8 年前

    在开始之前,我要提到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允许使用数据帧绘制分组条形图,其中每个列属于或构成一个组。

    1. 根据不同批次的数量创建多个子批次 variables .
    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 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 this question . 然而,自 海伯恩。条形图 plt。酒吧 多次,每次一次 ,每个调用中的错误将是相同的(或者它们的维度不匹配)。

    因此,我看到的唯一选择是使用 FacetGrid 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

    推荐文章