如何将平均线添加到 seaborn stripplot 或 swarmplot 中

BBQ*_*cus 11 python matplotlib boxplot seaborn swarmplot

我有一个带有垂直数据的相当简单的带状图。

planets = sns.load_dataset("planets")
sns.stripplot(x="method", y="distance", data=planets, size=4, color=".7")
plt.xticks(rotation=45, ha="right")
plt.show()
Run Code Online (Sandbox Code Playgroud)

我想将每个 x 元素 ( ) 的平均值绘制method为一个小水平条,类似于您得到的结果:

sns.boxplot(
    x="method",
    y="distance",
    data=planets,
    whis=[50, 50],
    showfliers=False,
    showbox=False,
    showcaps=False
)
Run Code Online (Sandbox Code Playgroud)

但没有第一/第三四分位数的垂直线(whis=[50,50]只有点),并且显示平均值而不是中位数。也许有一个更优雅的解决方案,不涉及箱线图。

Tre*_*ney 15

  • 箱线图对象定义于matplotlib.pyplot.boxplot
    • showmeans=True
    • meanline=True制作一条线而不是标记
    • meanprops={'color': 'k', 'ls': '-', 'lw': 2}设置线条的颜色、样式和宽度。
    • medianprops={'visible': False}使中线不可见
    • whiskerprops={'visible': False}使胡须线不可见
    • zorder=10将线放置在顶层
  • 测试于matplotlib v3.4.2seaborn v0.11.1
import seaborn as sns
import matplotlib.pyplot as plt

# load the dataset
planets = sns.load_dataset("planets")

p = sns.stripplot(x="method", y="distance", data=planets, size=4, color=".7")
plt.xticks(rotation=45, ha="right")
p.set(yscale='log')

# plot the mean line
sns.boxplot(showmeans=True,
            meanline=True,
            meanprops={'color': 'k', 'ls': '-', 'lw': 2},
            medianprops={'visible': False},
            whiskerprops={'visible': False},
            zorder=10,
            x="method",
            y="distance",
            data=planets,
            showfliers=False,
            showbox=False,
            showcaps=False,
            ax=p)
plt.show()
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

  • 与一个类似的工作原理seaborn.swarmplot

在此输入图像描述


mwa*_*kom 7

这是另一个类似于箱线图的想法,但需要较少的覆盖:绘制一个pointplot宽度为 0 的置信区间,并激活误差栏“caps”以获取具有可参数化宽度的水平线:

planets = sns.load_dataset("planets")
spec = dict(x="method", y="distance", data=planets)
sns.stripplot(**spec, size=4, color=".7")
sns.pointplot(**spec, join=False, ci=0, capsize=.7, scale=0)
plt.xticks(rotation=45, ha="right")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

这里明显的一个缺点是,对于具有单一观察的组,引导会被跳过,因此您不会在那里得到一条平均线。这在实际应用中可能是也可能不是问题。

另一个技巧是自己进行分组,然后用非常宽的垂直线标记绘制散点图:

planets = sns.load_dataset("planets")
variables = dict(x="method", y="distance")
sns.stripplot(data=planets, **variables, size=4, color=".7")
sns.scatterplot(
    data=planets.groupby("method")["distance"].mean().reset_index(),
    **variables, marker="|", s=2, linewidth=25
)
plt.xticks(rotation=45, ha="right")
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述


Sco*_*ton 5

ax.hlines这是使用查找平均值和列表理解的解决方案groupby

import seaborn as sns
import matplotlib.pyplot as plt

# load the dataset
planets = sns.load_dataset("planets")

p = sns.stripplot(x="method", y="distance", data=planets, size=4, color=".7", zorder=1)
plt.xticks(rotation=45, ha="right")
p.set(yscale='log');

df_mean = planets.groupby('method', sort=False)['distance'].mean()
_ = [p.hlines(y, i-.25, i+.25, zorder=2) for i, y in df_mean.reset_index()['distance'].items()]
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述