Скажем, я использую 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')
Как мне «обрезать» или «обрезать» строки, чтобы они отображались только под kde-функцией distplot? В результате должно получиться что-то вроде этого (быстро делается с помощью gimp):
Бонусный вопрос: как мне сделать то же самое с plt.fill_between()
, чтобы была заполнена только область под кривой? Я думаю, что мне не хватает чего-то легкого здесь. Я уже обрезал вызовы fill_between к другим элементам раньше, но я не знаю, как получить координаты функции и как это сделать с помощью линий.
Есть ли простой и лаконичный способ сделать то, что я хочу?
Вы можете сделать это, обратившись к плавной линии распределения, нанесенной distplot
. Что касается бонусной части, я бы рекомендовал задать новый вопрос и не смешивать две проблемы в одном вопросе.
Хитрость здесь заключается в том, чтобы получить значение x, ближайшее к low
, median
и high
, а затем использовать 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()
Один из способов сделать это — найти данные, соответствующие гладкой линии, которую 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]);
Надеюсь это поможет.