【问题标题】:How to overlay data points on a barplot with a categorical axis如何用分类轴覆盖条形图上的数据点
【发布时间】:2026-02-21 18:30:02
【问题描述】:

目标:我正在尝试使用 Seaborn 在具有多个分组条形图的图中显示单个数据点。

问题:我尝试使用条形图的 catplot 和单个数据点的另一个 catplot 来做到这一点。但是,这会生成 2 个图形:一个带有条形图,另一个带有单个数据点。

问题:有没有办法使用 Seaborn 将单个数据点与条形图一起显示在同一图中?

这是我的代码生成 2 个单独的数字:

import seaborn as sns
tips = sns.load_dataset("tips")

g = sns.catplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    row="time", 
    data=tips, 
    kind="bar", 
    ci = "sd", 
    edgecolor="black",
    errcolor="black",
    errwidth=1.5,
    capsize = 0.1,
    height=4, 
    aspect=.7,
)

g = sns.catplot(
    x="sex", 
    y="total_bill", 
    hue="smoker", 
    row="time", 
    data=tips, 
    kind="strip", 
    height=4, 
    aspect=.7,
)

输出:

问题:有没有办法使用 Seaborn 将单个数据点与条形图一起显示在同一图中?

【问题讨论】:

    标签: python matplotlib seaborn bar-chart facet-grid


    【解决方案1】:
    • seaborn.catplot 是图形级别的情节,不能合并。
    • 如下所示,seaborn.barplotseaborn.stripplot 等轴级图可以绘制到相同的 axes
    import seaborn as sns
    
    tips = sns.load_dataset("tips")
    
    ax = sns.barplot(
        x="sex", 
        y="total_bill", 
        hue="smoker", 
        data=tips, 
        ci="sd", 
        edgecolor="black",
        errcolor="black",
        errwidth=1.5,
        capsize = 0.1,
        alpha=0.5
    )
    
    sns.stripplot(
        x="sex", 
        y="total_bill", 
        hue="smoker", 
        data=tips, dodge=True, alpha=0.6, ax=ax
    )
    
    # remove extra legend handles
    handles, labels = ax.get_legend_handles_labels()
    ax.legend(handles[2:], labels[2:], title='Smoker', bbox_to_anchor=(1, 1.02), loc='upper left')
    

    【讨论】:

    • @Trenton McKinney 感谢您引导我找到更好的答案。
    • 不客气!
    • 谢谢!但是,如我的代码部分 (row="time") 中所述,如何在具有多行或多列的图中的条形图上叠加数据点。有没有办法做到这一点? @特伦顿麦金尼
    • @AlexSchubert 请参阅How to plot in multiple subplots 创建具有多行和多列的子图,然后将条形图和条形图分配给相同的轴。
    【解决方案2】:
    • 图形级图 (seaborn.catplot) 可能无法合并,但是可以将轴级图 (seaborn.stripplot) 映射到图形级图。
    • python 3.8.11matplotlib 3.4.3seaborn 0.11.2 中测试
    import seaborn as sns
    
    tips = sns.load_dataset("tips")
    
    g = sns.catplot(
        x="sex", 
        y="total_bill", 
        hue="smoker", 
        row="time", 
        data=tips, 
        kind="bar", 
        ci = "sd", 
        edgecolor="black",
        errcolor="black",
        errwidth=1.5,
        capsize = 0.1,
        height=4, 
        aspect=.7,
        alpha=0.5)
    
    # map data to stripplot
    g.map(sns.stripplot, 'sex', 'total_bill', 'smoker', hue_order=['Yes', 'No'], order=['Male', 'Female'],
          palette=sns.color_palette(), dodge=True, alpha=0.6, ec='k', linewidth=1)
    

    【讨论】: