Jak stworzyć wykres gęstości w matplotlib?

122

W RI można stworzyć pożądane wyjście, wykonując:

data = c(rep(1.5, 7), rep(2.5, 2), rep(3.5, 8),
         rep(4.5, 3), rep(5.5, 1), rep(6.5, 8))
plot(density(data, bw=0.5))

Wykres gęstości w R.

W Pythonie (z matplotlib) najbliższy otrzymałem był z prostym histogramem:

import matplotlib.pyplot as plt
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
plt.hist(data, bins=6)
plt.show()

Histogram w matplotlib

Próbowałem również użyć parametru normed = True, ale nie mogłem uzyskać niczego innego niż próba dopasowania gaussa do histogramu.

Moje ostatnie próby były w pobliżu scipy.statsi gaussian_kdepodążając za przykładami w Internecie, ale jak dotąd mi się nie udało.

unode
źródło
Zajrzyj na seaborn stackoverflow.com/a/32803224/1922302
johk95

Odpowiedzi:

124

Sven pokazał, jak używać klasy gaussian_kdez Scipy, ale zauważysz, że nie wygląda to tak, jak to, co wygenerowałeś za pomocą R. Dzieje się tak, ponieważ gaussian_kdepróbuje automatycznie wywnioskować przepustowość. Można grać z pasma w sposób, poprzez zmianę funkcji covariance_factorw gaussian_kdeklasie. Po pierwsze, oto co otrzymujesz bez zmiany tej funkcji:

tekst alternatywny

Jeśli jednak użyję następującego kodu:

import matplotlib.pyplot as plt
import numpy as np
from scipy.stats import gaussian_kde
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = gaussian_kde(data)
xs = np.linspace(0,8,200)
density.covariance_factor = lambda : .25
density._compute_covariance()
plt.plot(xs,density(xs))
plt.show()

dostaję

tekst alternatywny

co jest bardzo zbliżone do tego, co otrzymujesz od R. Co ja zrobiłem? gaussian_kdewykorzystuje zmienną funkcję covariance_factordo obliczenia swojej przepustowości. Przed zmianą funkcji wartość zwracana przez covariance_factor dla tych danych wynosiła około 0,5. Obniżenie tego zmniejszyło przepustowość. Musiałem zadzwonić _compute_covariancepo zmianie tej funkcji, aby wszystkie czynniki zostały poprawnie obliczone. Nie jest to dokładna zgodność z parametrem bw z R, ale miejmy nadzieję, że pomaga to we właściwym kierunku.

Justin Peel
źródło
6
@Justin Niezła odpowiedź (+1) i nie chcę rozpoczynać żadnych wojen płomieni w Pythonie v R ani cokolwiek innego, ale podoba mi się sposób, w jaki R działa z danymi znacznie bardziej zwięźle niż Python i inne języki. Jestem pewien, że Python ma wiele zalet w porównaniu z R (nie jestem użytkownikiem Pythona, więc jestem całkowicie umundurowany, aby ewentualnie komentować) i może być używany do znacznie większej pracy niż analizowanie danych, ale jako długoletnia R użytkownik Zapominam, jak zwięzły jest język do takich zadań, dopóki nie pojawią się takie przykłady.
Gavin Simpson
4
(wciąż walczymy z edytowaniem komentarzy) Oto podklasa gaussian_kde, która pozwala ustawić przepustowość jako argument i więcej przykładów: mail.scipy.org/pipermail/scipy-user/2010- stycznia / 023877.html i jest ulepszenie bilet na projects.scipy.org/scipy/ticket/1092 . Uwaga, gaussian_kde jest zaprojektowany dla danych n-wymiarowych.
Josef
11
@Gavin Simpson, tak, R jest bardziej zwięzły, ponieważ ma węższy zakres. Służy do obliczeń statystycznych i grafiki. Python to ogólny język programowania, który może robić prawie wszystko, co chcesz. Z tego powodu składnia może nie być tak zwięzła. Częścią tego jest inny projekt w Numpy / Scipy, ale część to tylko modułowa konfiguracja w Pythonie. R jest świetny, jeśli potrzebujesz tylko obliczeń i grafiki, ale jeśli potrzebujesz tych obliczeń w jakiejś aplikacji brader, możesz chcieć czegoś takiego jak Python. Jednak możesz także użyć R z Pythona ...
Justin Peel,
10
ZA set_bandwidthSposób i bw_methodargumentem konstruktora dodano gaussian_kde w scipy 0.11.0 za numerze 1619
eddygeek
1
nieaktualna odpowiedź. Zobacz poniżej rozwiązanie Seaborn, które jest teraz bardziej standardowe w Pythonie.
LudvigH
148

Pięć lat później, kiedy wyszukuję w Google „jak stworzyć wykres gęstości jądra za pomocą Pythona”, ten wątek wciąż pojawia się na górze!

Dziś dużo łatwiejszym sposobem na to jest użycie jelita morskiego , pakietu, który zapewnia wiele wygodnych funkcji kreślenia i dobre zarządzanie stylami .

import numpy as np
import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.set_style('whitegrid')
sns.kdeplot(np.array(data), bw=0.5)

wprowadź opis obrazu tutaj

Xin
źródło
Dziękuję bardzo… Szukałem czegoś takiego od wielu dni… czy u proszę wyjaśnić, dlaczego to bw=0.5jest podane?
Sitz Blogz
4
@SitzBlogz bwParametr oznacza przepustowość. Próbowałem dopasować ustawienia OP (zobacz jego oryginalny przykład pierwszego kodu). Aby uzyskać szczegółowe wyjaśnienie, jakie bwelementy sterujące, zobacz en.wikipedia.org/wiki/… . Zasadniczo kontroluje, jak gładki ma być wykres gęstości. Im większe bw, tym bardziej gładkie będzie.
Xin
Mam inne zapytanie, aby zapytać, czy moje dane mają charakter dyskretny i próbuję wykreślić w tym celu plik PDF, po przeczytaniu dokumentu scipy zrozumiałem, że PMF = PDF ma jakieś sugestie, jak to wykreślić?
Sitz Blogz
1
Kiedy próbuję tego, dostajęTypeError: slice indices must be integers or None or have an __index__ method
endolith
48

Opcja 1:

Użyj pandaswykresu ramki danych (zbudowanego na wierzchu matplotlib):

import pandas as pd
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
pd.DataFrame(data).plot(kind='density') # or pd.Series()

wprowadź opis obrazu tutaj

Opcja 2:

Skorzystaj distplotz seaborn:

import seaborn as sns
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
sns.distplot(data, hist=False)

wprowadź opis obrazu tutaj

Aziz Alto
źródło
4
Aby dodać parametr przepustowości: df.plot.density (bw_method = 0.5)
Anake
3
@Aziz Nie trzeba pandas.DataFrame, można używać pandas.Series(data).plot(kind='density')@Anake, nie trzeba ustawiać df.plot.density jako oddzielnego kroku; możesz po prostu przejść w swoim bw_methodkwargu dopd.Series(data).plot(kind='density', bw_method=0.5)
The Red Pea,
45

Może spróbuj czegoś takiego:

import matplotlib.pyplot as plt
import numpy
from scipy import stats
data = [1.5]*7 + [2.5]*2 + [3.5]*8 + [4.5]*3 + [5.5]*1 + [6.5]*8
density = stats.kde.gaussian_kde(data)
x = numpy.arange(0., 8, .1)
plt.plot(x, density(x))
plt.show()

Możesz łatwo zastąpić gaussian_kde()innym oszacowaniem gęstości jądra.

Sven Marnach
źródło
0

Wykres gęstości można również utworzyć za pomocą matplotlib: Funkcja plt.hist (dane) zwraca wartości y i x niezbędne do sporządzenia wykresu gęstości (patrz dokumentacja https://matplotlib.org/3.1.1/api/_as_gen/ matplotlib.pyplot.hist.html ). W rezultacie poniższy kod tworzy wykres gęstości przy użyciu biblioteki matplotlib:

import matplotlib.pyplot as plt
dat=[-1,2,1,4,-5,3,6,1,2,1,2,5,6,5,6,2,2,2]
a=plt.hist(dat,density=True)
plt.close()
plt.figure()
plt.plot(a[1][1:],a[0])      

Ten kod zwraca następujący wykres gęstości

wprowadź opis obrazu tutaj

tetrisforjeff
źródło