Як створити графік щільності в matplotlib?


122

У RI можна створити бажаний вихід, виконавши:

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

У python (з matplotlib) найближче мені було з простою гістограмою:

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

Гістограма в матплотлібі

Я також спробував параметр normed = True, але не міг отримати нічого іншого, крім спроби приєднати гаусса до гістограми.

Мої останні спроби були навколо, scipy.statsі gaussian_kde, наслідуючи приклади в Інтернеті, але я поки що невдалий.


Подивіться на seaborn stackoverflow.com/a/32803224/1922302
johk95

Відповіді:


124

Свен показав, як користуватися класом gaussian_kdeвід Scipy, але ви помітите, що він не схожий на те, що ви створили з R. Це тому, що gaussian_kdeнамагається автоматично провести смугу пропускання. Ви можете грати з пропускною спроможністю таким чином, змінюючи функцію covariance_factorз gaussian_kdeкласу. По-перше, ось що ви отримуєте, не змінюючи цю функцію:

alt текст

Однак якщо я використовую такий код:

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

я отримав

alt текст

що досить близько до того, що ви отримуєте від Р. Що я зробив? gaussian_kdeвикористовує змінну функцію covariance_factorдля обчислення її пропускної здатності. Перед зміною функції значення, повернене коваріацією_фактор для цих даних, становило близько .5. Понизивши це, зменшилася пропускна здатність. Мені довелося зателефонувати _compute_covarianceпісля зміни цієї функції, щоб усі фактори були обчислені правильно. Це не точне відповідність параметру bw від R, але, сподіваємось, це допоможе вам дістатись у правильному напрямку.


6
@Justin Nice відповідь (+1), і не хочу розпочинати жодних полум'яних воєн Python v R чи будь-чого іншого, але я люблю те, як R працює з даними набагато коротше, ніж python та інші мови. Я впевнений, що python має багато хороших балів за R (я не користувач Python, тому я так повністю уніфікований, що можливо коментувати) і його можна використовувати для набагато більшої роботи, ніж для аналізу даних, але як давно R Користувач, я забуваю, наскільки лаконічною є мова для таких завдань, поки не з'являться приклади, як це
Гевін Сімпсон

4
( По- , як і раніше бореться з редагуванням коментарів) Ось підклас gaussian_kde , що дозволяє встановити пропускну здатність в якості аргументу і інших прикладів: mail.scipy.org/pipermail/scipy-user/2010-January/023877.html і є підвищення Квиток на projekt.scipy.org/scipy/ticket/1092 . Зауважте, gaussian_kde призначений для n-мірних даних.
Йозеф

11
@Gavin Simpson, так, R є більш лаконічним, оскільки він має вузьку сферу застосування. Він зроблений для статистичних обчислень та графіки. Python - це загальна мова програмування, яка може робити майже все, що ви хочете. Через це синтаксис може бути не таким стислим. Частина цього - це інший дизайн у Numpy / Scipy, але частина - просто модульна настройка на Python. R чудово, якщо вам потрібно робити лише обчислення та графіку, але якщо вам потрібно використовувати ці обчислення в більш сміливому аплікатоїні, то, можливо, вам захочеться щось на зразок Python. Однак ви також можете використовувати R від Python ...
Джастін Піл

10
set_bandwidthМетод і bw_methodконструктор аргумент були додані до gaussian_kde в SciPy 0.11.0 на випуск 1619
eddygeek

1
застаріла відповідь. Дивіться нижче про рішення Seaborn, яке є більш стандартним для Python зараз.
LudvigH

148

Через п'ять років, коли я Google "як створити графік щільності ядра за допомогою python", ця нитка все ще з’являється вгорі!

Сьогодні набагато простішим способом зробити це - використання морського немовляти , пакета, який забезпечує безліч зручних функцій побудови графіків та гарне управління стилем.

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)

введіть тут опис зображення


Дякую вам велике .. Шукали щось подібне з днів .. Ви можете, будь ласка, пояснити, чому bw=0.5дається?
Sitz Blogz

4
@SitzBlogz bwПараметр означає пропускну здатність. Я намагався відповідати налаштуванню ОП (див. Його оригінальний приклад першого коду). Для більш докладного пояснення про те, що bwелементи управління, см en.wikipedia.org/wiki / ... . В основному він контролює, наскільки гладким ви хочете бути плоттю щільності. Чим більша цибуля, тим вона буде більш гладкою.
Сінь

У мене є ще один запит, щоб запитати мої дані дискретні за своєю суттю, і я намагаюся скласти для цього PDF-файл, після прочитання через scipy doc я зрозумів, що PMF = PDF будь-які пропозиції щодо того, як їх розмістити?
Sitz Blogz

1
Коли я спробую це, я отримуюTypeError: slice indices must be integers or None or have an __index__ method
ендоліт

48

Варіант 1:

Використовуйте pandasграфік даних фрейму (побудований зверху 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()

введіть тут опис зображення

Варіант 2:

Використання distplotв 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)

введіть тут опис зображення


4
Щоб додати параметр пропускної здатності: df.plot.density (bw_method = 0,5)
Anake

3
@Aziz Не потрібно pandas.DataFrame, можна використовувати pandas.Series(data).plot(kind='density')@Anake, не потрібно встановлювати df.plot.density як окремий крок; може просто перейти у ваш bw_methodкваргpd.Series(data).plot(kind='density', bw_method=0.5)
Червоний горох

45

Можливо, спробуйте щось на кшталт:

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

Ви можете легко замінити gaussian_kde()на іншу оцінку щільності ядра.


0

Діаграма щільності також може бути створена за допомогою matplotlib: Функція plt.hist (дані) повертає значення y та x, необхідні для графіку щільності (див. Документацію https://matplotlib.org/3.1.1/api/_as_gen/ matplotlib.pyplot.hist.html ). У результаті наступний код створює графік щільності за допомогою бібліотеки 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])      

Цей код повертає наступний графік щільності

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.