จะสร้างพล็อตความหนาแน่นใน 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()

ฮิสโตแกรมใน matplotlib

ฉันลองใช้พารามิเตอร์ normed = True ด้วยแต่ไม่สามารถหาอะไรได้นอกจากพยายามทำให้ gaussian พอดีกับฮิสโตแกรม

ความพยายามครั้งล่าสุดของฉันเกิดขึ้นscipy.statsและgaussian_kdeเป็นไปตามตัวอย่างบนเว็บ แต่ฉันไม่ประสบความสำเร็จ


ดูได้ที่seaborn stackoverflow.com/a/32803224/1922302
johk95

คำตอบ:


124

Sven ได้แสดงวิธีใช้คลาสgaussian_kdeจาก Scipy แต่คุณจะสังเกตได้ว่ามันดูไม่ค่อยเหมือนกับสิ่งที่คุณสร้างด้วย R เนื่องจากgaussian_kdeพยายามที่จะอนุมานแบนด์วิดท์โดยอัตโนมัติ คุณสามารถเล่นกับแบนด์วิดท์ได้โดยเปลี่ยนฟังก์ชันcovariance_factorของgaussian_kdeคลาส ขั้นแรกนี่คือสิ่งที่คุณจะได้รับโดยไม่ต้องเปลี่ยนฟังก์ชันนั้น:

ข้อความแสดงแทน

อย่างไรก็ตามหากฉันใช้รหัสต่อไปนี้:

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

ฉันเข้าใจ

ข้อความแสดงแทน

ซึ่งค่อนข้างใกล้เคียงกับสิ่งที่คุณได้รับจาก R ฉันทำอะไรไปบ้าง? gaussian_kdeใช้ฟังก์ชันที่เปลี่ยนแปลงได้covariance_factorเพื่อคำนวณแบนด์วิดท์ ก่อนที่จะเปลี่ยนฟังก์ชันค่าที่ส่งกลับโดย covariance_factor สำหรับข้อมูลนี้คือประมาณ 0.5 การลดแบนด์วิดท์นี้จะลดลง ฉันต้องโทร_compute_covarianceหลังจากเปลี่ยนฟังก์ชันนั้นเพื่อให้คำนวณปัจจัยทั้งหมดได้อย่างถูกต้อง ไม่ใช่ความสอดคล้องที่แน่นอนกับพารามิเตอร์ bw จาก R แต่หวังว่าจะช่วยให้คุณไปในทิศทางที่ถูกต้อง


6
@ จัสตินคำตอบที่ดี (+1) และไม่ต้องการเริ่มสงครามเปลวไฟ Python v R หรืออะไรเลย แต่ฉันชอบวิธีที่ R ทำงานกับข้อมูลอย่างรวบรัดกว่า python และภาษาอื่น ๆ ฉันแน่ใจว่า python มีจุดที่ดีมากกว่า R (ฉันไม่ใช่ผู้ใช้ Python ดังนั้นฉันจึงมีความเป็นไปได้ที่จะแสดงความคิดเห็นโดยสิ้นเชิง) และสามารถใช้งานได้มากกว่าการวิเคราะห์ข้อมูล แต่เป็น R ที่ใช้เวลานาน ผู้ใช้ฉันลืมไปว่าภาษานั้นกระชับแค่ไหนสำหรับงานดังกล่าวจนกระทั่งตัวอย่างเช่นการครอบตัดนี้
Gavin Simpson

4
(ยังคงต่อสู้กับการแก้ไขความคิดเห็น) นี่คือคลาสย่อยของ gaussian_kde ที่อนุญาตให้ตั้งค่าแบนด์วิดท์เป็นอาร์กิวเมนต์และตัวอย่างเพิ่มเติม: mail.scipy.org/pipermail/scipy-user/2010-January/023877.htmlและมีการปรับปรุง ตั๋วที่projects.scipy.org/scipy/ticket/1092 หมายเหตุ gaussian_kde ออกแบบมาสำหรับข้อมูล n มิติ
Josef

11
@Gavin Simpson ใช่ R จะรวบรัดกว่าเพราะมีขอบเขตที่แคบกว่า สร้างขึ้นเพื่อการคำนวณทางสถิติและกราฟิก Python เป็นภาษาโปรแกรมทั่วไปที่สามารถทำอะไรก็ได้ที่คุณต้องการ ด้วยเหตุนี้ไวยากรณ์จึงอาจไม่กระชับ ส่วนหนึ่งคือการออกแบบที่แตกต่างกันใน Numpy / Scipy แต่ส่วนหนึ่งเป็นเพียงการตั้งค่าแบบแยกส่วนบน Python R นั้นยอดเยี่ยมหากคุณต้องการเพียงแค่การคำนวณและกราฟิก แต่ถ้าคุณต้องการใช้การคำนวณเหล่านั้นในแอปพลิเคชั่น Brader คุณอาจต้องการบางอย่างเช่น Python อย่างไรก็ตามคุณยังสามารถใช้ R จาก Python ได้ ...
Justin Peel

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พารามิเตอร์ย่อมาจากแบนด์วิดท์ ฉันพยายามจับคู่การตั้งค่าของ OP (ดูตัวอย่างโค้ดแรกดั้งเดิมของเขา) สำหรับคำอธิบายรายละเอียดของสิ่งที่bwควบคุมดูen.wikipedia.org/wiki/... โดยทั่วไปจะควบคุมว่าคุณต้องการให้พล็อตความหนาแน่นเป็นอย่างไร ยิ่ง BW ใหญ่เท่าไหร่ก็จะยิ่งเรียบมากขึ้นเท่านั้น
ซิน

ฉันมีคำถามอื่นที่จะถามว่าข้อมูลของฉันไม่ต่อเนื่องและฉันกำลังพยายามพล็อต PDF สำหรับสิ่งนั้นหลังจากอ่านเอกสาร scipy ฉันเข้าใจว่า PMF = PDF มีข้อเสนอแนะเกี่ยวกับวิธีการลงจุดหรือไม่
Sitz Blogz

1
เมื่อฉันลองสิ่งนี้ฉันได้รับTypeError: slice indices must be integers or None or have an __index__ method
endolith

48

ตัวเลือกที่ 1:

ใช้pandasdataframe plot (สร้างที่ด้านบน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)
เอนก

3
@Aziz ไม่จำเป็นpandas.DataFrameสามารถใช้pandas.Series(data).plot(kind='density')@Anake ไม่จำเป็นต้องตั้งค่า df.plot.density เป็นขั้นตอนแยกต่างหาก สามารถส่งผ่านbw_methodkwarg ของคุณไปยังpd.Series(data).plot(kind='density', bw_method=0.5)
The Red Pea

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 (data) ส่งคืนค่า 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])      

รหัสนี้ส่งคืนพล็อตความหนาแน่นต่อไปนี้

ใส่คำอธิบายภาพที่นี่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.