【问题标题】:How to add a mean and median line to a Seaborn displot如何将平均线和中线添加到 Seaborn 分布图
【发布时间】:2021-08-09 07:37:35
【问题描述】:

有没有办法将平均值和中位数添加到 Seaborn 的 displot

penguins = sns.load_dataset("penguins")
g = sns.displot(
    data=penguins, x='body_mass_g',
    col='species',  
    facet_kws=dict(sharey=False, sharex=False)
)

基于Add mean and variability to seaborn FacetGrid distplots,我看到我可以定义一个FacetGrid 并映射一个函数。我可以将自定义函数传递给displot吗?

尝试直接使用displot 的原因是,这些图开箱即用更漂亮,无需调整刻度标签大小、轴标签大小等,并且在视觉上与我正在制作的其他图一致。

def specs(x, **kwargs):
    ax = sns.histplot(x=x)
    ax.axvline(x.mean(), color='k', lw=2)
    ax.axvline(x.median(), color='k', ls='--', lw=2)

g = sns.FacetGrid(data=penguins, col='species')
g.map(specs,'body_mass_g' )

【问题讨论】:

    标签: python matplotlib seaborn histogram


    【解决方案1】:

    选项 1

    • 使用plt. 而不是ax
      • 在 OP 中,vlines 将转到 axhistplot,但在这里,该图是在 .map 之前创建的。
    penguins = sns.load_dataset("penguins")
    g = sns.displot(
        data=penguins, x='body_mass_g',
        col='species',  
        facet_kws=dict(sharey=False, sharex=False)
    )
    
    def specs(x, **kwargs):
        plt.axvline(x.mean(), c='k', ls='-', lw=2.5)
        plt.axvline(x.median(), c='orange', ls='--', lw=2.5)
    
    g.map(specs,'body_mass_g' )
    

    选项 2

    • 此选项更详细,但更灵活,因为它允许从用于创建displot 的数据源以外的数据源访问和添加信息。
    import seaborn as sns
    import pandas as pd
    
    # load the data
    pen = sns.load_dataset("penguins")
    
    # groupby to get mean and median
    pen_g = pen.groupby('species').body_mass_g.agg(['mean', 'median'])
    
    g = sns.displot(
        data=pen, x='body_mass_g',
        col='species',  
        facet_kws=dict(sharey=False, sharex=False)
    )
    # extract and flatten the axes from the figure
    axes = g.axes.flatten()
    
    # iterate through each axes
    for ax in axes:
        # extract the species name
        spec = ax.get_title().split(' = ')[1]
        
        # select the data for the species
        data = pen_g.loc[spec, :]
        
        # print data as needed or comment out
        print(data)
        
        # plot the lines
        ax.axvline(x=data['mean'], c='k', ls='-', lw=2.5)
        ax.axvline(x=data['median'], c='orange', ls='--', lw=2.5)
    

    两个选项的输出

    资源

    【讨论】:

      【解决方案2】:

      这里可以使用sns.FacetGrid.facet_data 来迭代子图和底层数据的索引。

      这与 sns.FacetGrid.map 在底层的工作方式很接近。 sns.FacetGrid.facet_data 是一个生成器,它产生一个包含行、列、色调索引的元组 (i, j, k)data,它是一个 DataFrame,它是与每个方面对应的完整数据的子集。

      import seaborn as sns
      import pandas as pd
      
      
      pen = sns.load_dataset("penguins")
      
      # Set our x_var for later use
      x_var = "body_mass_g"
      
      g = sns.displot(
          data=pen,
          x=x_var,
          col="species",
          facet_kws=dict(sharey=False, sharex=False),
      )
      
      for (row, col, hue_idx), data in g.facet_data():
          # Skip empty data
          if not data.values.size:
              continue
      
          # Get the ax for `row` and `col`
          ax = g.facet_axis(row, col)
          # Set the `vline`s using the var `x_var`
          ax.axvline(data[x_var].mean(), c="k", ls="-", lw=2.5)
          ax.axvline(data[x_var].median(), c="orange", ls="--", lw=2.5)
      

      哪些输出:

      【讨论】:

        猜你喜欢
        • 2021-08-01
        • 2022-06-11
        • 2019-01-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-12
        • 2020-12-31
        相关资源
        最近更新 更多