剪切/裁剪线并在seaborn distplot kde函数上填充matplotlib

时间:2019-05-28 09:57:40

标签: python matplotlib seaborn

假设我使用seaborn绘制分布,它是这样的中位数和标准差:

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

# Get data
data = np.random.randn(6000)

# Compute statistics
median = np.median(data)
sigma = np.std(data)

low = median - sigma
hi = median + sigma

# Plot
sns.distplot(data)
plt.axvline(median, c='r')
plt.axvline(low, c='k')
plt.axvline(hi, c='k')

enter image description here

我该如何“裁剪”或“剪切”线,使其仅出现在distplot的kde函数下方?结果应该是这样的(用gimp快速完成):

enter image description here

奖金问题:如何使用plt.fill_between()做同样的事情,以便仅填充曲线下方的区域?我想我在这里缺少容易的事情。我之前已经将fill_between调用剪切到其他元素,但是我不知道如何获取函数的坐标以及如何使用行。

是否有一种简单明了的方式来做我想做的事情?

2 个答案:

答案 0 :(得分:3)

一种方法是找到与kdeplot添加到图形的平滑线相对应的数据,并使用其x和y坐标。

下面的代码假定图中只有一条线---我们必须找出多条线与kdeplot线相对应。

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.interpolate import interp1d

# Get data
data = np.random.randn(6000)

# Compute statistics
median = np.median(data)
sigma = np.std(data)

low = median - sigma
hi = median + sigma

ax = sns.distplot(data)
# get the line that sns uses for kdeplot; at this point in the code 
# there is only one line; if there are more we need to exract the correct
# one.
line = ax.lines[0].get_data()
# To get y for x=low, x=high and x=median we can interpolate the line data
ipf = interp1d(x=line[0], y=line[1])

ax.plot([low, low], [0, ipf(low)])
ax.plot([hi, hi], [0, ipf(hi)])
ax.plot([median, median], [0, ipf(median)]);

Line to kdeplot

我们可以将行数据用作fill_between的输入。

plt.fill_between(line[0], np.zeros(len(line[0])), line[1]);

Line to kdeplot and fill_between

希望这会有所帮助。

答案 1 :(得分:1)

您可以通过访问distplot绘制的平滑分布线来实现。至于奖金部分,我建议您提出一个新问题,并且不要在同一问题中混淆两个问题。

这里的技巧是获得最接近lowmedianhigh的x值,然后使用plt.ylines而不是plt.axvline绘制一个y = 0到所需y值的垂直线。

# Plot
ax = sns.distplot(data)
x, y = ax.get_lines()[0].get_data()
plt.vlines(median, 0, y[np.argmin(abs(x-median))], color='r')
plt.vlines(low, 0, y[np.argmin(abs(x-low))], color='k')
plt.vlines(hi, 0, y[np.argmin(abs(x-hi))], color='k')
plt.show()

enter image description here