2010-10-05 46 views
56

Tôi muốn vẽ biểu đồ bình thường hóa từ một véc tơ sử dụng matplotlib. Tôi thử như sau:vẽ biểu đồ các biểu đồ có chiều cao thanh lên tới 1 trong matplotlib

plt.hist(myarray, normed=True) 

cũng như:

plt.hist(myarray, normed=1) 

nhưng không phải tùy chọn tạo ra một trục y từ [0, 1] như vậy mà chiều cao thanh của tổng histogram để 1. Tôi muốn tạo ra một biểu đồ như vậy - làm sao tôi có thể làm được?

cảm ơn!

+1

Tôi biết điều này là cũ, nhưng để tham khảo trong tương lai & bất cứ ai đến thăm trang này, loại trục lây lan được gọi là một "mật độ xác suất" trục! – ChristineB

+0

OP nếu bạn vẫn ở xung quanh có thể bạn muốn thay đổi câu trả lời được chấp nhận. –

Trả lời

39

Sẽ hữu ích hơn nếu bạn đặt một ví dụ hoàn chỉnh hơn (hoặc trong trường hợp này không hoạt động).

tôi thử như sau:

import numpy as np 
import matplotlib.pyplot as plt 

x = np.random.randn(1000) 

fig = plt.figure() 
ax = fig.add_subplot(111) 
n, bins, rectangles = ax.hist(x, 50, normed=True) 
fig.canvas.draw() 
plt.show() 

này thực sự sẽ tạo ra một biểu đồ thanh biểu đồ với một trục y mà đi từ [0,1].

Hơn nữa, theo các tài liệu hist (tức ax.hist? từ ipython), tôi nghĩ số tiền là tốt quá:

*normed*: 
If *True*, the first element of the return tuple will 
be the counts normalized to form a probability density, i.e., 
``n/(len(x)*dbin)``. In a probability density, the integral of 
the histogram should be 1; you can verify that with a 
trapezoidal integration of the probability density function:: 

    pdf, bins, patches = ax.hist(...) 
    print np.sum(pdf * np.diff(bins)) 

Cho một thử này sau khi các lệnh trên:

np.sum(n * np.diff(bins)) 

tôi nhận được giá trị trả lại là 1.0 như mong đợi. Hãy nhớ rằng normed=True không có nghĩa là tổng giá trị tại mỗi thanh sẽ là sự thống nhất, nhưng thay vì tích phân trên các thanh là sự thống nhất. Trong trường hợp của tôi np.sum(n) trả lại khoảng 7.2767.

13

Tôi biết câu trả lời này là quá muộn khi xem câu hỏi là ngày 2010 nhưng tôi đã xem qua câu hỏi này vì tôi đang đối mặt với một vấn đề tương tự. Như đã nêu trong câu trả lời, chuẩn = True có nghĩa là tổng diện tích dưới biểu đồ bằng 1 nhưng tổng chiều cao không bằng 1. Tuy nhiên, tôi muốn, để thuận tiện cho việc diễn giải vật lý của biểu đồ, hãy tạo một với tổng chiều cao bằng 1.

tôi tìm thấy một gợi ý trong những câu dưới đây - Python: Histogram with area normalized to something other than 1

Nhưng tôi đã không thể tìm thấy một cách để làm cho thanh bắt chước các histtype = "bước" tính năng hist(). Điều này đã chuyển hướng tôi đến: Matplotlib - Stepped histogram with already binned data

Nếu cộng đồng thấy nó có thể chấp nhận được, tôi nên đưa ra một giải pháp tổng hợp ý tưởng từ cả hai bài đăng trên.

import matplotlib.pyplot as plt 

# Let X be the array whose histogram needs to be plotted. 
nx, xbins, ptchs = plt.hist(X, bins=20) 
plt.clf() # Get rid of this histogram since not the one we want. 

nx_frac = nx/float(len(nx)) # Each bin divided by total number of objects. 
width = xbins[1] - xbins[0] # Width of each bin. 
x = np.ravel(zip(xbins[:-1], xbins[:-1]+width)) 
y = np.ravel(zip(nx_frac,nx_frac)) 

plt.plot(x,y,linestyle="dashed",label="MyLabel") 
#... Further formatting. 

này đã làm việc tuyệt vời đối với tôi mặc dù trong một số trường hợp tôi đã nhận thấy rằng trái nhất "thanh" hoặc quyền nhất "thanh" của biểu đồ không đóng cửa bằng cách chạm vào điểm thấp nhất của Y- trục. Trong trường hợp này, thêm một phần tử 0 vào lúc ăn xin hoặc kết thúc của y đạt được kết quả cần thiết.

Chỉ nghĩ rằng tôi muốn chia sẻ kinh nghiệm của mình. Cảm ơn bạn.

+0

tôi nghĩ rằng bạn cần chuẩn hóa = True cũng như trong plt.hist. Cũng trong Python 3 bạn phải sử dụng danh sách (zip (...)). –

146

Nếu bạn muốn tổng của tất cả quán bar để được thống nhất bằng nhau, trọng lượng mỗi bin bằng tổng số giá trị:

weights = np.ones_like(myarray)/float(len(myarray)) 
plt.hist(myarray, weights=weights) 

Hy vọng rằng sẽ giúp, mặc dù chủ đề là khá cũ ...

+8

Câu trả lời hay. Lưu ý rằng nếu myarray là một python 'array_like' chứ không phải là một mảng numpy, bạn sẽ cần phải cast' len (myarray) 'vào' float'. – cmh

+0

Ngoài ra nếu myarray là đa chiều và bạn chỉ sử dụng một chiều, chẳng hạn như myarray [0 ,:], thì bạn có thể hoán đổi len (myarray) với np.size (myarray [0 ,:]) và nó sẽ hoạt động theo cùng một cách. (Nếu không, nó nói đối tượng không thể gọi được.) – ChristineB

8

Đây là một giải pháp đơn giản khác sử dụng phương pháp np.histogram().

myarray = np.random.random(100) 
results, edges = np.histogram(myarray, normed=True) 
binWidth = edges[1] - edges[0] 
plt.bar(edges[:-1], results*binWidth, binWidth) 

Bạn thực sự có thể kiểm tra xem tổng số tiền lên đến 1 với:

> print sum(results*binWidth) 
1.0 
Các vấn đề liên quan