2015-03-10 16 views
6

Próbuję zrobić Kernel Density Estimation (KDE) plot z seaborn i zlokalizować medianę. Kod wygląda mniej więcej tak:Jak zlokalizować medianę na działce KDE (seaborn)?

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

sns.set_palette("hls", 1) 
data = np.random.randn(30) 
sns.kdeplot(data, shade=True) 

# x_median, y_median = magic_function() 
# plt.vlines(x_median, 0, y_median) 

plt.show() 

Jak widać muszę magic_function() sprowadzić medianę wartości X i Y od kdeplot. Następnie chciałbym wykreślić je za pomocą np. vlines. Jednak nie mogę wymyślić, jak to zrobić. Wynik powinien wyglądać mniej więcej tak (oczywiście czarny mediana pasek jest źle tutaj):

enter image description here

Chyba moje pytanie nie jest ściśle związany z Seaborn i odnosi się także do innych rodzajów działek matplotlib. Wszelkie pomysły są bardzo cenne.

+0

Jestem nieco zdezorientowany twoim celem. Dlaczego nie tworzysz tylko 'np.median (danych)'? – mwaskom

+1

@mwaskom: Myślę, że próbowałem tego. ale mediana KDE niekoniecznie pokrywa się z medianą danych. A jaka byłaby wartość y? – n1000

Odpowiedz

12

Musisz:

  1. Wyodrębnianie danych z linii kde
  2. zintegrować go obliczyć dystrybuantę (CDF)
  3. Znajdź wartość, która sprawia CDF równy 1/2, że jest mediana
import numpy as np 
import scipy 
import seaborn as sns 
import matplotlib.pyplot as plt 

sns.set_palette("hls", 1) 
data = np.random.randn(30) 
p=sns.kdeplot(data, shade=True) 

x,y = p.get_lines()[0].get_data() 

#care with the order, it is first y 
#initial fills a 0 so the result has same length than x 
cdf = scipy.integrate.cumtrapz(y, x, initial=0) 

nearest_05 = np.abs(cdf-0.5).argmin() 

x_median = x[nearest_05] 
y_median = y[nearest_05] 

plt.vlines(x_median, 0, y_median) 
plt.show() 

Result

+0

doskonałe rozwiązanie! – n1000

+1

Jak możesz użyć tego rozwiązania, aby zrobić to samo dla średniej? – Tminer