Линии обрезки / обрезки и заливки в matplotlib на морском участке dist -lot kde-function - PullRequest
0 голосов
/ 28 мая 2019

Скажем, я использую 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

Как мне поступить«обрезать» или «обрезать» линии, чтобы они появлялись только под функцией kde в distplot?Результат должен быть примерно таким (быстро делается с gimp):

enter image description here

Бонусный вопрос: Как бы я поступил так же с plt.fill_between(),чтобы была заполнена только область под кривой?Я думаю, что я упускаю что-то легкое здесь.Я уже обрезал вызовы fill_between к другим элементам ранее, но я не знаю, как получить координаты функции и как это сделать со строками.

Существует ли простой и краткий способ сделать то, что яхочу?

Ответы [ 2 ]

3 голосов
/ 28 мая 2019

Один из способов сделать это - найти данные, которые соответствуют гладкой линии, которую 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 голос
/ 28 мая 2019

Вы можете сделать это, обратившись к гладкой линии раздачи, нанесенной 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()

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...