Làm thế nào để tạo một biểu đồ mật độ trong matplotlib?


122

Trong RI có thể tạo đầu ra mong muốn bằng cách thực hiện:

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

Biểu đồ mật độ trong R

Trong python (với matplotlib), điều gần nhất tôi nhận được là 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()

Biểu đồ trong matplotlib

Tôi cũng đã thử tham số Normed = True nhưng không thể nhận được gì khác ngoài việc cố gắng điều chỉnh một gaussian vào biểu đồ.

Những nỗ lực mới nhất của tôi đã diễn ra scipy.statsgaussian_kdetheo các ví dụ trên web, nhưng cho đến nay tôi vẫn chưa thành công.


Câu trả lời:


124

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

văn bản thay thế

Tuy nhiên, nếu tôi sử dụng 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 có

văn bản thay thế

khá gần với những gì bạn nhận được từ R. Tôi đã làm gì? gaussian_kdesử dụng một hàm có thể thay đổi covariance_factorđể tính toán băng thông của nó. Trước khi thay đổi hàm, giá trị được trả về bởi covariance_factor cho dữ liệu này là khoảng 0,5. Hạ thấp điều này làm giảm băng thông. Tôi đã phải gọi _compute_covariancesau khi thay đổi hàm đó để tất cả các yếu tố sẽ được tính toán chính xác. Nó không phải là 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.


6
@Justin Câu trả lời tốt đẹp (+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 kỳ thứ gì, nhưng tôi thích cách R làm việc với dữ liệu ngắn gọn hơn nhiều là python và các ngôn ngữ khác. Tôi chắc chắn rằng python có nhiều điểm tốt so với R (tôi không phải là người dùng Python nên tôi hoàn toàn thống nhất để có thể nhận xét) 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 với tư cách là một R lâu năm người dùng Tôi quên cách cô đọng ngôn ngữ cho các tác vụ như vậy cho đến khi các ví dụ như thế này xuất hiện.
Gavin Simpson

4
(vẫn đang chiến đấu với việc chỉnh sửa nhận xét) Đây là một lớp con của gaussian_kde cho phép đặt băng thông làm đối số và các ví dụ khác: mail.scipy.org/pipermail/scipy-user/2010-January/023877.html và có một cải tiến vé tại dự án.scipy.org/scipy/ticket/1092 . Lưu ý, gaussian_kde được thiết kế cho dữ liệu n chiều.
Josef

11
@Gavin Simpson, vâng, R ngắn gọn hơn vì nó có phạm vi hẹp hơn. Nó được tạo ra để tính toán thống kê và đồ họa. Python là một ngôn ngữ lập trình chung có thể làm được nhiều điều bạn muốn. Do đó, cú pháp có thể không ngắn gọn. Một phần là thiết kế khác trong Numpy / Scipy, nhưng một phần của nó chỉ là thiết lập mô-đun trên Python. R là tuyệt vời nếu bạn chỉ cần thực hiện các phép tính và đồ họa, nhưng nếu bạn cần sử dụng các tính toán đó trong một số ứng dụng táo bạo hơn, thì bạn có thể muốn một cái gì đó giống như Python. Tuy nhiên, bạn cũng có thể sử dụng R từ Python ...
Justin Peel

10
Một set_bandwidthphương pháp và bw_methodlý luận xây dựng đã được thêm vào gaussian_kde trong scipy 0.11.0 mỗi vấn đề 1619
eddygeek

1
câu trả lời lỗi thời. Xem bên dưới về giải pháp Seaborn, giải pháp này hiện chuẩn hơn trong Python.
LudvigH

148

Năm năm sau, khi tôi Google "cách tạo biểu đồ mật độ nhân bằng python", luồng này vẫn hiển thị ở trên cùng!

Ngày nay, một cách dễ dàng hơn nhiều để làm điều này là sử dụng seaborn , một gói cung cấp nhiều chức năng vẽ biểu đồ tiện lợi 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)

nhập mô tả hình ảnh ở đây


Cảm ơn bạn rất nhiều .. Bạn đã tìm kiếm một cái gì đó như thế này kể từ ngày .. bạn có thể giải thích tại sao bw=0.5được đưa ra không?
Sitz Blogz

4
@SitzBlogz bwTham số là viết tắt của băng thông. Tôi đang cố gắng khớp cài đặt của OP (xem ví dụ mã đầu tiên ban đầu của anh ấy). Để biết giải thích chi tiết về những bwđiều khiển nào, hãy xem en.wikipedia.org/wiki/… . Về cơ bản, nó kiểm soát mức độ mượt mà bạn muốn biểu đồ mật độ. Bw càng lớn thì càng mịn.
Xin

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

1
Khi tôi thử cái này, tôi nhận đượcTypeError: slice indices must be integers or None or have an __index__ method
endolith

48

Lựa chọn 1:

Sử dụng pandasbiểu đồ khung dữ liệu (được xây dựng trên đầu trang 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()

nhập mô tả hình ảnh ở đây

Lựa chọn 2:

Sử dụng distplotcủ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)

nhập mô tả hình ảnh ở đây


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

3
@Aziz Không cần pandas.DataFrame, có thể sử dụng pandas.Series(data).plot(kind='density')@Anake, không cần đặt df.plot.density làm bước riêng biệt; chỉ có thể vượt qua bw_methodkwarg của bạn vàopd.Series(data).plot(kind='density', bw_method=0.5)
The Red Pea

45

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ằng một ước tính mật độ nhân khác.


0

Biểu đồ mật độ cũng có thể được tạo bằng cách sử dụng matplotlib: Hàm plt.hist (dữ liệu) trả về các giá trị y và x cần thiết cho biểu đồ mật độ (xem tài liệu https://matplotlib.org/3.1.1/api/_as_gen/ matplotlib.pyplot.hist.html ). Do đó, đoạn mã sau tạo ra một biểu đồ mật độ bằng cách sử dụng thư viện 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])      

Mã này trả về biểu đồ mật độ sau

nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.