假设我使用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')
我该如何“裁剪”或“剪切”线,使其仅出现在distplot的kde函数下方?结果应该是这样的(用gimp快速完成):
奖金问题:如何使用plt.fill_between()
做同样的事情,以便仅填充曲线下方的区域?我想我在这里缺少容易的事情。我之前已经将fill_between调用剪切到其他元素,但是我不知道如何获取函数的坐标以及如何使用行。
是否有一种简单明了的方式来做我想做的事情?
答案 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)]);
我们可以将行数据用作fill_between
的输入。
plt.fill_between(line[0], np.zeros(len(line[0])), line[1]);
希望这会有所帮助。
答案 1 :(得分:1)
您可以通过访问distplot
绘制的平滑分布线来实现。至于奖金部分,我建议您提出一个新问题,并且不要在同一问题中混淆两个问题。
这里的技巧是获得最接近low
,median
和high
的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()