Matplotlib'de yoğunluk grafiği nasıl oluşturulur?


122

RI'da aşağıdakileri yaparak istenen çıktıyı oluşturabilirsiniz:

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))

R cinsinden yoğunluk grafiği

Python'da (matplotlib ile) elde ettiğim en yakın şey basit bir histogramdı:

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()

Matplotlib'de histogram

Ben de denedim Normlu = True parametresini , ancak histograma bir gaussian yerleştirmeye çalışmaktan başka bir şey elde edemedim.

Son girişimlerim ortalıktaydı scipy.statsve gaussian_kdeweb'deki örnekleri takip ediyordu , ancak şimdiye kadar başarısız oldum.


Yanıtlar:


124

Sven, gaussian_kdeScipy'den sınıfın nasıl kullanılacağını gösterdi, ancak bunun R ile oluşturduğunuza pek benzemediğini fark edeceksiniz. Bunun nedeni gaussian_kde, bant genişliğini otomatik olarak çıkarmaya çalışmasıdır. Sen fonksiyonunu değiştirerek şekilde bant genişliği ile oynayabilir covariance_factorait gaussian_kdesınıfına. İlk olarak, işte bu işlevi değiştirmeden elde edeceğiniz şey:

alternatif metin

Ancak, aşağıdaki kodu kullanırsam:

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()

alırım

alternatif metin

bu da R'den aldığınıza oldukça yakın. Ne yaptım? gaussian_kdecovariance_factorbant genişliğini hesaplamak için değiştirilebilir bir işlev kullanır . İşlevi değiştirmeden önce, bu veriler için kovaryans_faktörü tarafından döndürülen değer yaklaşık .5 idi. Bunu düşürmek bant genişliğini düşürdü. _compute_covarianceTüm faktörlerin doğru hesaplanması için bu işlevi değiştirdikten sonra aramak zorunda kaldım . Bu, R'deki bw parametresiyle tam bir uyuşma değildir, ancak umarım doğru yöne gitmenize yardımcı olur.


6
@Justin Güzel cevap (+1) ve herhangi bir Python v R alev savaşları veya başka bir şey başlatmak istemiyorum, ancak R'nin verilerle çalışma şeklini python ve diğer dillerden çok daha kısaca seviyorum. Eminim python'un R'ye göre pek çok iyi noktası vardır (Python kullanıcısı değilim, bu yüzden muhtemelen yorum yapmak için çok üniformalıyım) ve verileri analiz etmekten çok daha fazla iş için kullanılabilir, ancak uzun süredir R kullanıcı Böyle örnekler ortaya çıkana kadar bu tür görevler için ne kadar özlü bir dil olduğunu unutuyorum.
Gavin Simpson

4
(yorumları düzenleme konusunda hala mücadele ediyor) Burada, bant genişliğini bir argüman ve daha fazla örnek olarak ayarlamaya izin veren bir gaussian_kde alt sınıfı var : mail.scipy.org/pipermail/scipy-user/2010-January/023877.html ve bir geliştirme var Projects.scipy.org/scipy/ticket/1092 adresindeki bilet . Gaussian_kde'nin n boyutlu veriler için tasarlandığına dikkat edin.
Josef

11
@Gavin Simpson, evet, R daha kısa, çünkü daha dar bir kapsamı var. İstatistiksel hesaplama ve grafikler için yapılmıştır. Python, yapmasını istediğiniz her şeyi hemen hemen yapabilen genel bir programlama dilidir. Bu nedenle sözdizimi kısa ve öz olmayabilir. Bunun bir kısmı Numpy / Scipy'de farklı bir tasarımdır, ancak bir kısmı Python'daki modüler kurulumdur. Yalnızca hesaplamalar ve grafikler yapmanız gerekiyorsa R harikadır, ancak bu hesaplamaları bazı brader uygulamalarında kullanmanız gerekiyorsa, Python gibi bir şey isteyebilirsiniz. Bununla birlikte, Python'dan R'yi de kullanabilirsiniz ...
Justin Peel

10
set_bandwidthbw_method
Scipy'de

1
modası geçmiş cevap. Şimdi Python'da daha standart olan Seaborn çözümüne bakın.
LudvigH

148

Beş yıl sonra, "python kullanarak bir çekirdek yoğunluğu grafiği nasıl oluşturulur" Google'da Google'da bu iş parçacığı hala üstte görünüyor!

Bugün, bunu yapmanın çok daha kolay bir yolu , birçok uygun çizim işlevi ve iyi stil yönetimi sağlayan bir paket olan seaborn'u kullanmaktır .

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)

görüntü açıklamasını buraya girin


Çok teşekkür ederim .. Günlerden beri böyle bir şey bw=0.5arıyorum .. Lütfen neden verildiğini açıklayabilir misiniz?
Sitz Blogz

4
@SitzBlogz bwParametre, bant genişliğini ifade eder. OP'nin ayarına uymaya çalışıyordum (orijinal ilk kod örneğine bakın). Hangi bwkontrollerin ayrıntılı bir açıklaması için bkz. En.wikipedia.org/wiki/… . Temel olarak, yoğunluk grafiğinin ne kadar düzgün olmasını istediğinizi kontrol eder. Bw ne kadar büyükse o kadar pürüzsüz olur.
Xin

Verilerimin doğası gereği ayrı olduğunu sormam gereken başka bir sorgum var ve bunun için PDF'yi çizmeye çalışıyorum, scipy belgesini okuduktan sonra PMF = PDF'nin nasıl çizileceğine dair herhangi bir öneri olduğunu anladım.
Sitz Blogz

1
Bunu denediğimde anlıyorumTypeError: slice indices must be integers or None or have an __index__ method
endolith

48

Seçenek 1:

pandasDataframe grafiğini kullanın (üzerine inşa edilir 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()

görüntü açıklamasını buraya girin

Seçenek 2:

Kullanım distplotait 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)

görüntü açıklamasını buraya girin


4
Bant genişliği parametresini eklemek için: df.plot.density (bw_method = 0.5)
Anake

3
@Aziz İhtiyaç yok pandas.DataFrame, pandas.Series(data).plot(kind='density')@Anake kullanabilir , df.plot.density'yi ayrı bir adım olarak ayarlamanıza gerek yok; sadece bw_methodkwarg'ınızı içine atabilirsinizpd.Series(data).plot(kind='density', bw_method=0.5)
The Red Pea

45

Belki şöyle bir şey deneyin:

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()

Kolayca gaussian_kde()farklı bir çekirdek yoğunluğu tahminiyle değiştirebilirsiniz.


0

Yoğunluk grafiği matplotlib kullanılarak da oluşturulabilir: plt.hist (data) fonksiyonu, yoğunluk grafiği için gerekli y ve x değerlerini döndürür ( https://matplotlib.org/3.1.1/api/_as_gen/ belgelerine bakın. matplotlib.pyplot.hist.html ). Sonuç olarak, aşağıdaki kod matplotlib kitaplığını kullanarak bir yoğunluk grafiği oluşturur:

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])      

Bu kod aşağıdaki yoğunluk grafiğini döndürür

görüntü açıklamasını buraya girin

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.