如何在 kdeplot 上绘制 0 和平均值 y 值之间的平均线

问题描述 投票:0回答:2

我有一个 distplot,我想绘制一条从 0 到平均频率 y 值的平均线。 我想这样做,但是当 distplot 停止时,让该行停止。为什么没有一个简单的参数来做到这一点?这将非常有用。

我有一些代码可以帮助我实现目标:

plt.plot([x.mean(),x.mean()], [0, *what here?*])

这段代码按照我的意愿绘制了一条线,除了我想要的 y 值。让 y max 停止在分布图中平均值的频率处的正确数学是什么?下面是我的分布图之一的示例,使用 0.6 作为 y-max。如果有一些数学方法让它停在平均值的 y 值上,那就太棒了。我尝试过将平均值除以计数等。

python matplotlib seaborn distribution kdeplot
2个回答
24
投票

更新最新版本的 matplotlib (

3.3.4
) 和 seaborn (
0.13.3
):带有
shade=True
的 kdeplot 现在不再创建线条对象。为了获得与之前相同的结果,设置
fill=False
仍将创建线条对象。然后可以用
ax.fill_between()
填充曲线。下面的代码进行了相应的更改。 (使用修订历史记录查看旧版本。)

ax.lines[0]
获取kde的曲线,可以提取其中的x和y数据。
np.interp
然后可以找到给定 x 值的曲线高度:

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

x = np.random.normal(np.tile(np.random.uniform(10, 30, 5), 50), 3)
ax = sns.kdeplot(x, fill=False, color='crimson')
kdeline = ax.lines[0]
mean = x.mean()
xs = kdeline.get_xdata()
ys = kdeline.get_ydata()
height = np.interp(mean, xs, ys)
ax.vlines(mean, 0, height, color='crimson', ls=':')
ax.fill_between(xs, 0, ys, facecolor='crimson', alpha=0.2)
plt.show()

可以扩展相同的方法来显示平均值和标准差,或中位数和四分位数:

import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np

x = np.random.normal(np.tile(np.random.uniform(10, 30, 5), 50), 3)
fig, axes = plt.subplots(ncols=2, figsize=(12, 4))
for ax in axes:
    sns.kdeplot(x, fill=False, color='crimson', ax=ax)
    kdeline = ax.lines[0]
    xs = kdeline.get_xdata()
    ys = kdeline.get_ydata()
    if ax == axes[0]:
        middle = x.mean()
        sdev = x.std()
        left = middle - sdev
        right = middle + sdev
        ax.set_title('Showing mean and sdev')
    else:
        left, middle, right = np.percentile(x, [25, 50, 75])
        ax.set_title('Showing median and quartiles')
    ax.vlines(middle, 0, np.interp(middle, xs, ys), color='crimson', ls=':')
    ax.fill_between(xs, 0, ys, facecolor='crimson', alpha=0.2)
    ax.fill_between(xs, 0, ys, where=(left <= xs) & (xs <= right), interpolate=True, facecolor='crimson', alpha=0.2)
    # ax.set_ylim(ymin=0)
plt.show()

PS:kde的模式:

    mode_idx = np.argmax(ys)
    ax.vlines(xs[mode_idx], 0, ys[mode_idx], color='lime', ls='--')

3
投票

使用

plt.get_ylim()
,您可以获得当前绘图的限制:[bottomtop]。
因此,就您的情况而言,您可以提取实际限制并将其保存在
ylim
中,然后画线:

fig, ax = plt.subplots()

ylim = ax.get_ylim()
ax.plot([x.mean(),x.mean()], ax.get_ylim())
ax.set_ylim(ylim)

由于

ax.plot
之后会更改 ylims,因此您必须使用
ax.set_ylim
重新设置它们,如上所述。

© www.soinside.com 2019 - 2024. All rights reserved.