Plot dua histogram pada grafik tunggal dengan matplotlib

234

Saya membuat plot histogram menggunakan data dari file dan tidak ada masalah. Sekarang saya ingin menempatkan data dari file lain dalam histogram yang sama, jadi saya melakukan sesuatu seperti ini

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

tetapi masalahnya adalah untuk setiap interval, hanya bilah dengan nilai tertinggi yang muncul, dan yang lainnya disembunyikan. Saya bertanya-tanya bagaimana saya bisa memetakan kedua histogram secara bersamaan dengan warna yang berbeda.

Buka jalannya
sumber

Jawaban:

418

Di sini Anda memiliki contoh yang berfungsi:

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

masukkan deskripsi gambar di sini

joaquin
sumber
1
Bukankah itu ide yang baik untuk ditetapkan pyplot.hold(True)sebelum merencanakan, untuk berjaga-jaga?
JAB
2
Tidak yakin apakah hold (True) disetel di parplig config matplotlib saya atau pyplot berperilaku seperti ini secara default, tetapi bagi saya kodenya berfungsi apa adanya. Kode ini diekstraksi dari aplikasi yang lebih besar yang sejauh ini tidak memberikan masalah. Ngomong-ngomong, pertanyaan bagus sudah saya buat untuk diri saya sendiri ketika menulis kode
joaquin
@ jooaquin: bagaimana saya bisa menentukan x menjadi biru dan y menjadi merah?
amc
7
Ketika saya mereproduksi plot dengan warna warna bar secara Nonedefault. Jika Anda ingin desain yang sama seperti yang ditunjukkan pada grafik, Anda dapat mengatur edgecolorparameter di keduanya misalnya menjadi k(hitam). Prosedurnya mirip untuk legenda.
Jadi S
2
Bahkan lebih mudah: pyplot.hist([x, y], bins, alpha=0.5, label=['x', 'y']).
Augustin
174

Jawaban yang diterima memberikan kode untuk histogram dengan bilah yang tumpang tindih, tetapi jika Anda ingin setiap bilah saling berdampingan (seperti yang saya lakukan), coba variasi di bawah ini:

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

masukkan deskripsi gambar di sini

Referensi: http://matplotlib.org/examples/statistics/histogram_demo_multihist.html

EDIT [2018/03/16]: Diperbarui untuk memungkinkan plot array dengan ukuran berbeda, seperti yang disarankan oleh @stochastic_zeitgeist

Gustavo Bezerra
sumber
@ GustavoBezerra, bagaimana cara menggunakan plt.histuntuk menghasilkan satu file pdf untuk setiap histogram? Saya memuat data saya menggunakan pandas.read_csvdan file memiliki 36 kolom dan 100 baris. Jadi saya ingin 100 file pdf.
Sigur
2
@ Konfigurasi Itu cukup banyak topik. Silakan Google atau ajukan pertanyaan baru. Ini sepertinya terkait: stackoverflow.com/questions/11328958/…
Gustavo Bezerra
1
@stochastic_zeitgeist Saya setuju dengan @pasbi. Saya menggunakan komentar Anda dengan kerangka data panda karena saya membutuhkan bobot yang berbeda karena nans. dengan x=np.array(df.a)dan y=np.array(df.b.dropna())pada dasarnya berakhir menjadiplt.hist([x, y], weights=[np.ones_like(x)/len(x), np.ones_like(y)/len(y)])
grinsbaeckchen
1
Jika ukuran sampel Anda sangat berbeda, Anda mungkin ingin merencanakan menggunakan sumbu kembar untuk membandingkan distribusi dengan lebih baik. Lihat di bawah .
Andrew
1
@ AgapeGal'lo Silakan merujuk ke jawaban Andrew.
Gustavo Bezerra
30

Jika Anda memiliki ukuran sampel yang berbeda, mungkin sulit untuk membandingkan distribusi dengan sumbu y tunggal. Sebagai contoh:

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

Dalam hal ini, Anda dapat memplot dua set data Anda pada sumbu yang berbeda. Untuk melakukannya, Anda bisa mendapatkan data histogram Anda menggunakan matplotlib, bersihkan porosnya, dan kemudian plot ulang pada dua sumbu terpisah (menggeser tepi nampan sehingga tidak tumpang tindih):

#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

Andrew
sumber
1
Ini adalah jawaban singkat yang bagus kecuali Anda juga harus menambahkan cara memusatkan bar pada setiap label centang
Odisseo
12

Sebagai pelengkap jawaban Gustavo Bezerra :

Jika Anda ingin setiap histogram dinormalisasi ( normeduntuk mpl <= 2.1 dan densityuntuk mpl> = 3.1 ) Anda tidak bisa hanya menggunakan normed/density=True, Anda perlu mengatur bobot untuk setiap nilai sebagai gantinya:

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

masukkan deskripsi gambar di sini

Sebagai perbandingan, sama persis xdan yvektor dengan bobot default dan density=True:

masukkan deskripsi gambar di sini

jojo
sumber
9

Anda harus menggunakan binsdari nilai yang dikembalikan oleh 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)

Dua histogram matplotlib dengan binning yang sama

Adrien Renaud
sumber
7

Berikut adalah metode sederhana untuk memplot dua histogram, dengan bilah mereka berdampingan, pada plot yang sama ketika data memiliki ukuran yang berbeda:

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()
stochastic_zeitgeist
sumber
2

Hanya dalam kasus Anda memiliki panda ( import pandas as pd) atau tidak apa-apa dengan menggunakannya:

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()
serv-inc
sumber
Saya percaya menggunakan panda tidak akan berfungsi jika histogram yang akan dibandingkan memiliki ukuran sampel yang berbeda. Ini juga sering merupakan konteks di mana histogram normal digunakan.
Solomon Vimal
2

Ada satu peringatan ketika Anda ingin memplot histogram dari array numpy 2-d. Anda perlu menukar 2 sumbu.

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

masukkan deskripsi gambar di sini

黄锐铭
sumber
0

Pertanyaan ini telah dijawab sebelumnya, tetapi ingin menambahkan solusi cepat / mudah lain yang mungkin membantu pengunjung lain ke pertanyaan ini.

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

Beberapa contoh bermanfaat ada di sini untuk perbandingan kde vs histogram.

Solomon Vimal
sumber
0

Terinspirasi oleh jawaban Solomon, tetapi untuk tetap dengan pertanyaan, yang terkait dengan histogram, solusi bersih adalah:

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

Pastikan untuk merencanakan yang lebih tinggi terlebih dahulu, jika tidak, Anda perlu mengatur plt.ylim (0,0.45) agar histogram yang lebih tinggi tidak dipotong.

Sarah
sumber
0

Juga merupakan opsi yang sangat mirip dengan jawaban 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()

Memberikan hasil sebagai berikut:

masukkan deskripsi gambar di sini

PV8
sumber