2010-11-10 34 views
84

Trong RI có thể tạo ra kết quả mong muốn bằng cách thực hiện:Làm thế nào để tạo ra một cốt truyện mật độ trong matplotlib?

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

Density plot in R

Trong python (với matplotlib) gần nhất tôi nhận được với một biểu đồ đơn giản:

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 in matplotlib

Tôi cũng đã thử sử dụng the normed=True parameter nhưng không thể kiếm được bất kỳ điều gì khác ngoài việc cố gắng phù hợp với một gaussian để biểu đồ.

Lần thử mới nhất của tôi là khoảng scipy.statsgaussian_kde, ví dụ sau trên web, nhưng tôi đã không thành công cho đến nay.

+0

Hãy nhìn vào 'seaborn' https://stackoverflow.com/a/32803224/1922302 – johk95

Trả lời

95

Sven đã chỉ ra cách sử dụng lớp gaussian_kde từ Scipy, nhưng bạn sẽ nhận thấy rằng nó không giống như những gì bạn đã tạo với R. Điều này là do gaussian_kde cố gắng suy ra băng thông tự động. Bạn có thể chơi với băng thông theo cách bằng cách thay đổi hàm covariance_factor của lớp gaussian_kde. Thứ nhất, đây là những gì bạn nhận được mà không thay đổi chức năng:

alt text

Tuy nhiên, nếu tôi sử dụng đoạn mã sau:

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

tôi nhận được

alt text

đó là khá gần với những gì bạn đang nhận được từ R. Tôi đã làm gì? gaussian_kde sử dụng chức năng có thể thay đổi, covariance_factor để tính băng thông của nó. Trước khi thay đổi hàm, giá trị trả về bởi covariance_factor cho dữ liệu này là khoảng 0,5. Hạ thấp băng thông này. Tôi đã phải gọi _compute_covariance sau khi thay đổi chức năng đó để tất cả các yếu tố sẽ được tính toán chính xác. Nó không phải là một sự tương ứng chính xác với tham số bw từ R, nhưng hy vọng nó sẽ giúp bạn đi đúng hướng.

+5

@Justin Câu trả lời hay (+1) và không muốn bắt đầu bất kỳ cuộc chiến tranh ngọn lửa Python v R hay bất cứ điều gì, nhưng tôi yêu cách R làm việc với dữ liệu ngắn gọn hơn mà trăn và các ngôn ngữ khác. Tôi chắc rằng python có rất nhiều điểm tốt trên R (Tôi không phải là người dùng Python vì vậy tôi hoàn toàn đồng nhất để có thể bình luận) và có thể được sử dụng cho nhiều công việc hơn là phân tích dữ liệu, nhưng như một thời gian dài R người dùng, tôi quên mất một ngôn ngữ ngắn gọn như thế nào cho những công việc như vậy cho đến khi các ví dụ như thế này được tạo ra. –

+0

đây là phân lớp của gaussian_kde cho phép đặt băng thông làm đối số. – user333700

+4

(vẫn đang chiến đấu với các bình luận chỉnh sửa) Đây là một phân lớp của gaussian_kde cho phép thiết lập băng thông làm đối số và nhiều ví dụ hơn: http://mail.scipy.org/pipermail/scipy-user/2010-January/023877.html và có một vé tăng cường tại http://projects.scipy.org/scipy/ticket/1092. Lưu ý, gaussian_kde được thiết kế cho dữ liệu n-chiều. – user333700

36

Có thể thử một cái gì đó như:

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

Bạn có thể dễ dàng thay thế gaussian_kde() bởi một ước tính mật độ hạt nhân khác nhau.

+1

1 cho ví dụ làm việc và đã gần với đầu ra mong muốn – Unode

+0

Sau khi thử nhiều nhất trên trang này - cảm ơn bạn. –

83

Năm năm sau, khi tôi Google "cách tạo cốt truyện mật độ hạt nhân bằng cách sử dụng python", chuỗi này vẫn hiển thị ở trên cùng!

Hôm nay, cách dễ dàng hơn để thực hiện việc này là sử dụng seaborn, một gói cung cấp nhiều chức năng âm mưu thuận tiện và quản lý kiểu tốt.

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) 

enter image description here

+0

Cảm ơn bạn rất nhiều .. Đã tìm kiếm một cái gì đó như thế này kể từ ngày .. u có thể giải thích tại sao 'bw = 0,5' được đưa ra? –

+1

@SitzBlogz Tham số 'bw' là viết tắt của băng thông. Tôi đã cố gắng để phù hợp với thiết lập của OP (xem ví dụ mã đầu tiên ban đầu của mình). Để có giải thích chi tiết về điều khiển 'bw', hãy xem https://en.wikipedia.org/wiki/Kernel_density_estimation#Bandwidth_selection.Về cơ bản nó kiểm soát mức độ mượt mà bạn muốn cốt truyện mật độ. Các bw lớn hơn, mịn hơn nó sẽ được. – Xin

+0

Tôi có một truy vấn khác để hỏi dữ liệu của tôi là rời rạc trong tự nhiên và tôi đang cố gắng vẽ bản PDF cho điều đó, sau khi đọc qua tài liệu scipy tôi hiểu rằng PMF = PDF bất kỳ đề xuất nào về cách vẽ đồ thị? –

24

Lựa chọn 1:

Sử dụng pandas cốt truyện dataframe (được xây dựng trên đầu trang của 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() 

enter image description here

Phương án 2:

Sử dụng distplot của 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) 

enter image description here

+3

Để thêm tham số băng thông: df.plot.density (bw_method = 0.5) – Anake

+0

@Aziz Không cần' gấu trúc. DataFrame', có thể sử dụng 'pandas.Series (data) .plot (type = 'density')' @Anake, không cần đặt df.plot.density là một bước riêng biệt; chỉ có thể vượt qua trong 'bw_method' kwarg của bạn vào' pd.Series (dữ liệu) .plot (type = 'density', bw_method = 0.5) ' –

+1

@ TheRedPea thực sự cảm ơn :-) Tôi vừa cập nhật câu trả lời của mình. –

Các vấn đề liên quan