【问题标题】:Labeling boxplot in seaborn with median value在seaborn中用中值标记箱线图
【发布时间】:2016-12-03 14:54:23
【问题描述】:

如何用中值标记 seaborn 图中的每个箱线图?

例如

import seaborn as sns
sns.set_style("whitegrid")
tips = sns.load_dataset("tips")
ax = sns.boxplot(x="day", y="total_bill", data=tips)

如何用中值或平均值标记每个箱线图?

【问题讨论】:

    标签: python matplotlib seaborn


    【解决方案1】:

    我喜欢人们包含样本数据集!

    import seaborn as sns
    
    sns.set_style("whitegrid")
    tips = sns.load_dataset("tips")
    box_plot = sns.boxplot(x="day",y="total_bill",data=tips)
    
    medians = tips.groupby(['day'])['total_bill'].median()
    vertical_offset = tips['total_bill'].median() * 0.05 # offset from median for display
    
    for xtick in box_plot.get_xticks():
        box_plot.text(xtick,medians[xtick] + vertical_offset,medians[xtick], 
                horizontalalignment='center',size='x-small',color='w',weight='semibold')
    

    【讨论】:

    • 请注意,中位数[tick] 后 0.5 的影响对数据的规模很敏感。对于我的小规模,它将白色文本推到白色背景中,我花了一段时间才弄清楚为什么它没有显示。根据需要缩放 0.5。
    • 注意:上面的np.round(s, 2)可以只替换为s;此外,这里不需要zip()get_xticklabels() 命令。这里的诀窍是每个标签的位置由中值本身(作为 y 值)和分类标签(我猜是由沿 x 轴的整数表示)(作为 x 值)确定。如果您要注释的信息存储在数据框中,则提取 xticklabels 可能会有所帮助,因为您可以使用 xticklabels 进行索引。
    • 哈! +1 我喜欢人们包含示例数据集!。我也是。
    【解决方案2】:

    这也可以通过从图本身导出中值来实现,而无需专门从数据中计算中值

    box_plot = sns.boxplot(x="day", y="total_bill", data=tips)
    
    ax = box_plot.axes
    lines = ax.get_lines()
    categories = ax.get_xticks()
    
    for cat in categories:
        # every 4th line at the interval of 6 is median line
        # 0 -> p25 1 -> p75 2 -> lower whisker 3 -> upper whisker 4 -> p50 5 -> upper extreme value
        y = round(lines[4+cat*6].get_ydata()[0],1) 
    
        ax.text(
            cat, 
            y, 
            f'{y}', 
            ha='center', 
            va='center', 
            fontweight='bold', 
            size=10,
            color='white',
            bbox=dict(facecolor='#445A64'))
    
    box_plot.figure.tight_layout()
    

    【讨论】:

    • 效果很好!备注:如果禁用传单,则间隔从 6 变为 5(由于缺少传单-“线”)。所以现在我必须考虑一种技术,如何让这个技术适用于通过色调值分组的数据......
    【解决方案3】:

    基于 ShikjarDua 的方法,我创建了一个独立于刻度位置的版本。这在处理 seaborn 中的分组数据时会派上用场(即 hue=parameter)。此外,我添加了一个“飞行器检测”,它会更改每个绘制框的线条。

    import seaborn as sns
    import matplotlib.pyplot as plt
    import matplotlib.patheffects as path_effects
    
    def add_median_labels(ax, precision='.1f'):
        lines = ax.get_lines()
        boxes = [c for c in ax.get_children() if type(c).__name__ == 'PathPatch']
        lines_per_box = int(len(lines) / len(boxes))
        for median in lines[4:len(lines):lines_per_box]:
            x, y = (data.mean() for data in median.get_data())
            # choose value depending on horizontal or vertical plot orientation
            value = x if (median.get_xdata()[1] - median.get_xdata()[0]) == 0 else y
            text = ax.text(x, y, f'{value:{precision}}', ha='center', va='center',
                           fontweight='bold', color='white')
            # create median-colored border around white text for contrast
            text.set_path_effects([
                path_effects.Stroke(linewidth=3, foreground=median.get_color()),
                path_effects.Normal(),
            ])
    
    sns.set_style("darkgrid")
    tips = sns.load_dataset("tips")
    fig, axes = plt.subplots(2, 2, figsize=(10, 10))
    for i_fly, show_fliers in enumerate([True, False]):
        for i_data, data_kwargs in enumerate([{'x': 'day', 'y': 'total_bill'},
                                              {'y': 'day', 'x': 'total_bill'}]):
            ax = sns.boxplot(ax=axes[i_fly, i_data], **data_kwargs, data=tips,
                                   showfliers=show_fliers, hue="sex")
            add_median_labels(ax)
            ax.set_title((
                f"{['Fliers', 'No fliers'][i_fly]}, "
                f"{['vertical', 'horizontal'][i_data]}"))
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-07-01
      • 2018-07-02
      • 2019-01-31
      • 2020-08-27
      • 1970-01-01
      • 2020-10-31
      • 1970-01-01
      • 2021-11-06
      相关资源
      最近更新 更多