Vẽ hai biểu đồ trên biểu đồ đơn với matplotlib


233

Tôi đã tạo một biểu đồ biểu đồ bằng cách sử dụng dữ liệu từ một tệp và không có vấn đề gì. Bây giờ tôi muốn chồng dữ liệu từ một tệp khác trong cùng biểu đồ, vì vậy tôi làm một cái gì đó như thế này

n,bins,patchs = ax.hist(mydata1,100)
n,bins,patchs = ax.hist(mydata2,100)

nhưng vấn đề là ở mỗi khoảng thời gian, chỉ có thanh có giá trị cao nhất xuất hiện và thanh kia bị ẩn. Tôi tự hỏi làm thế nào tôi có thể vẽ cả hai biểu đồ cùng một lúc với các màu khác nhau.

Câu trả lời:


417

Ở đây bạn có một ví dụ làm việc:

import random
import numpy
from matplotlib import pyplot

x = [random.gauss(3,1) for _ in range(400)]
y = [random.gauss(4,2) for _ in range(400)]

bins = numpy.linspace(-10, 10, 100)

pyplot.hist(x, bins, alpha=0.5, label='x')
pyplot.hist(y, bins, alpha=0.5, label='y')
pyplot.legend(loc='upper right')
pyplot.show()

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


1
Sẽ không phải là một ý tưởng tốt để thiết lập pyplot.hold(True)trước khi âm mưu, chỉ trong trường hợp?
JAB

2
Không chắc chắn nếu giữ (True) được đặt trong thông số cấu hình matplotlib hoặc pyplot của tôi hoạt động như thế này theo mặc định, nhưng đối với tôi mã hoạt động như vậy. Mã được trích xuất từ ​​một ứng dụng lớn hơn mà không gây ra vấn đề gì cho đến nay. Dù sao, câu hỏi hay tôi đã tự đặt ra khi viết mã
joaquin

@joaquin: làm thế nào tôi có thể chỉ định x là màu xanh và y là màu đỏ?
amc

7
Khi tôi tái tạo cốt truyện với edgecolor của các thanh Nonetheo mặc định. Nếu bạn muốn thiết kế giống như trong biểu đồ, bạn có thể đặt edgecolortham số trong cả hai ví dụ thành k(màu đen). Thủ tục tương tự cho truyền thuyết.
Vì vậy,

2
Thậm chí dễ dàng hơn : pyplot.hist([x, y], bins, alpha=0.5, label=['x', 'y']).
Augustin

174

Các câu trả lời được chấp nhận cung cấp mã cho biểu đồ với các thanh chồng chéo, nhưng trong trường hợp bạn muốn mỗi thanh nằm cạnh nhau (như tôi đã làm), hãy thử biến thể bên dưới:

import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-deep')

x = np.random.normal(1, 2, 5000)
y = np.random.normal(-1, 3, 2000)
bins = np.linspace(-10, 10, 30)

plt.hist([x, y], bins, label=['x', 'y'])
plt.legend(loc='upper right')
plt.show()

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

Tham khảo: http://matplotlib.org/examples/statistic/histogram_demo_multihist.html

EDIT [2018/03/16]: Được cập nhật để cho phép vẽ các mảng có kích thước khác nhau, theo đề xuất của @stochastic_zeitgeist


@GustavoBezerra, làm thế nào để sử dụng plt.histđể tạo một tệp pdf cho mỗi biểu đồ? Tôi đã tải dữ liệu của mình bằng cách sử dụng pandas.read_csvvà tệp có 36 cột và 100 dòng. Vì vậy, tôi muốn 100 tập tin pdf.
Sigur

2
@Sigur Điều đó khá lạc đề. Vui lòng Google hoặc đặt câu hỏi mới. Điều này dường như có liên quan: stackoverflow.com/questions/11328958/ Kẻ
Gustavo Bezerra

1
@stochastic_zeitgeist Tôi đồng ý với @pasbi. Tôi đã sử dụng nhận xét của bạn với một khung dữ liệu gấu trúc vì tôi cần các trọng số khác nhau do các nans. với x=np.array(df.a)y=np.array(df.b.dropna())về cơ bản nó đã kết thúcplt.hist([x, y], weights=[np.ones_like(x)/len(x), np.ones_like(y)/len(y)])
grinsbaeckchen

1
Trong trường hợp kích thước mẫu của bạn khác nhau đáng kể, bạn có thể muốn vẽ đồ thị bằng cách sử dụng trục đôi để so sánh tốt hơn các bản phân phối. Xem bên dưới .
Andrew

1
@ AgapeGal'lo Vui lòng tham khảo câu trả lời của Andrew.
Gustavo Bezerra

30

Trong trường hợp bạn có các cỡ mẫu khác nhau, có thể khó so sánh các phân phối với một trục y. Ví dụ:

import numpy as np
import matplotlib.pyplot as plt

#makes the data
y1 = np.random.normal(-2, 2, 1000)
y2 = np.random.normal(2, 2, 5000)
colors = ['b','g']

#plots the histogram
fig, ax1 = plt.subplots()
ax1.hist([y1,y2],color=colors)
ax1.set_xlim(-10,10)
ax1.set_ylabel("Count")
plt.tight_layout()
plt.show()

hist_single_ax

Trong trường hợp này, bạn có thể vẽ hai tập dữ liệu của mình trên các trục khác nhau. Để làm như vậy, bạn có thể lấy dữ liệu biểu đồ của mình bằng matplotlib, xóa trục và sau đó vẽ lại nó trên hai trục riêng biệt (dịch chuyển các cạnh của thùng sao cho chúng không trùng nhau):

#sets up the axis and gets histogram data
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.hist([y1, y2], color=colors)
n, bins, patches = ax1.hist([y1,y2])
ax1.cla() #clear the axis

#plots the histogram data
width = (bins[1] - bins[0]) * 0.4
bins_shifted = bins + width
ax1.bar(bins[:-1], n[0], width, align='edge', color=colors[0])
ax2.bar(bins_shifted[:-1], n[1], width, align='edge', color=colors[1])

#finishes the plot
ax1.set_ylabel("Count", color=colors[0])
ax2.set_ylabel("Count", color=colors[1])
ax1.tick_params('y', colors=colors[0])
ax2.tick_params('y', colors=colors[1])
plt.tight_layout()
plt.show()

hist_twin_ax


1
Đây là một câu trả lời ngắn gọn, ngoại trừ bạn cũng nên thêm cách căn giữa các thanh trên mỗi nhãn đánh dấu
Odisseo

12

Như một sự hoàn thành cho câu trả lời của Gustavo Bezerra :

Nếu bạn muốn mỗi biểu đồ được chuẩn hóa ( normedđối với mpl <= 2.1 và densityđối với mpl> = 3.1 ), bạn không thể chỉ sử dụng normed/density=True, bạn cần đặt trọng số cho từng giá trị thay thế:

import numpy as np
import matplotlib.pyplot as plt

x = np.random.normal(1, 2, 5000)
y = np.random.normal(-1, 3, 2000)
x_w = np.empty(x.shape)
x_w.fill(1/x.shape[0])
y_w = np.empty(y.shape)
y_w.fill(1/y.shape[0])
bins = np.linspace(-10, 10, 30)

plt.hist([x, y], bins, weights=[x_w, y_w], label=['x', 'y'])
plt.legend(loc='upper right')
plt.show()

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

Để so sánh, chính xác xycác vectơ có trọng số mặc định và density=True:

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


9

Bạn nên sử dụng binstừ các giá trị được trả về bởi hist:

import numpy as np
import matplotlib.pyplot as plt

foo = np.random.normal(loc=1, size=100) # a normal distribution
bar = np.random.normal(loc=-1, size=10000) # a normal distribution

_, bins, _ = plt.hist(foo, bins=50, range=[-6, 6], normed=True)
_ = plt.hist(bar, bins=bins, alpha=0.5, normed=True)

Hai biểu đồ matplotlib với cùng một binning


7

Đây là một phương pháp đơn giản để vẽ hai biểu đồ, với các thanh của chúng cạnh nhau, trên cùng một âm mưu khi dữ liệu có kích thước khác nhau:

def plotHistogram(p, o):
    """
    p and o are iterables with the values you want to 
    plot the histogram of
    """
    plt.hist([p, o], color=['g','r'], alpha=0.8, bins=50)
    plt.show()


2

Chỉ trong trường hợp bạn có gấu trúc ( import pandas as pd) hoặc ổn khi sử dụng nó:

test = pd.DataFrame([[random.gauss(3,1) for _ in range(400)], 
                     [random.gauss(4,2) for _ in range(400)]])
plt.hist(test.values.T)
plt.show()

Tôi tin rằng việc sử dụng gấu trúc sẽ không hiệu quả nếu biểu đồ được so sánh có các cỡ mẫu khác nhau. Đây cũng thường là bối cảnh trong đó biểu đồ chuẩn hóa được sử dụng.
Solomon Vimal

2

Có một cảnh báo khi bạn muốn vẽ biểu đồ từ một mảng numpy 2-d. Bạn cần hoán đổi 2 trục.

import numpy as np
import matplotlib.pyplot as plt

data = np.random.normal(size=(2, 300))
# swapped_data.shape == (300, 2)
swapped_data = np.swapaxes(x, axis1=0, axis2=1)
plt.hist(swapped_data, bins=30, label=['x', 'y'])
plt.legend()
plt.show()

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


0

Câu hỏi này đã được trả lời trước đây, nhưng muốn thêm một cách giải quyết nhanh / dễ dàng khác có thể giúp những khách truy cập khác vào câu hỏi này.

import seasborn as sns 
sns.kdeplot(mydata1)
sns.kdeplot(mydata2)

Một số ví dụ hữu ích ở đây để so sánh kde vs biểu đồ.


0

Lấy cảm hứng từ câu trả lời của Solomon, nhưng để gắn bó với câu hỏi liên quan đến biểu đồ, một giải pháp sạch sẽ là:

sns.distplot(bar)
sns.distplot(foo)
plt.show()

Trước tiên, hãy đảm bảo vẽ đồ thị của người cao hơn, nếu không bạn sẽ cần đặt plt.ylim (0,0,45) để biểu đồ cao hơn không bị cắt nhỏ.


0

Ngoài ra một tùy chọn khá giống với câu trả lời của joaquin:

import random
from matplotlib import pyplot

#random data
x = [random.gauss(3,1) for _ in range(400)]
y = [random.gauss(4,2) for _ in range(400)]

#plot both histograms(range from -10 to 10), bins set to 100
pyplot.hist([x,y], bins= 100, range=[-10,10], alpha=0.5, label=['x', 'y'])
#plot legend
pyplot.legend(loc='upper right')
#show it
pyplot.show()

Cung cấp đầu ra 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.