it-swarm.com.de

Zeichnen Sie zwei Histogramme gleichzeitig mit matplotlib

Ich habe ein Histogramm-Diagramm mit Daten aus einer Datei erstellt, und das ist kein Problem. Jetzt wollte ich Daten aus einer anderen Datei im selben Histogramm überlagern, also mache ich so etwas wie

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

das Problem ist jedoch, dass für jedes Intervall nur der Balken mit dem höchsten Wert angezeigt wird und der andere ausgeblendet wird. Ich frage mich, wie ich beide Histogramme gleichzeitig mit unterschiedlichen Farben zeichnen könnte.

189
Open the way

Hier haben Sie ein Arbeitsbeispiel:

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

enter image description here

353
joaquin

Die akzeptierten Antworten geben den Code für ein Histogramm mit überlappenden Balken an. Wenn Sie jedoch möchten, dass jeder Balken nebeneinander angezeigt wird (wie ich es getan habe), probieren Sie die folgende Variante:

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

enter image description here

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

EDIT [2018/03/16]: Aktualisiert, um das Plotten von Arrays unterschiedlicher Größe zu ermöglichen, wie von @stochastic_zeitgeist vorgeschlagen

131
Gustavo Bezerra

Wenn Sie unterschiedliche Stichprobengrößen haben, kann es schwierig sein, die Verteilungen mit einer einzelnen y-Achse zu vergleichen. Zum Beispiel:

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

In diesem Fall können Sie Ihre beiden Datensätze auf verschiedenen Achsen zeichnen. Zu diesem Zweck können Sie Ihre Histogrammdaten mit matplotlib abrufen, die Achse löschen und dann auf zwei separaten Achsen neu zeichnen (wobei die Bin-Kanten verschoben werden, damit sie sich nicht überlappen):

#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

24
Andrew

Hier ist eine einfache Methode, um zwei Histogramme mit ihren Balken nebeneinander im selben Diagramm zu zeichnen, wenn die Daten unterschiedliche Größen haben:

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

Als Ergänzung zu Gustavo Bezerras Antwort :

Wenn Sie möchten, dass jedes Histogramm normalisiert wird (normed für mpl <= 2.1 und density für mpl> = 3.1) du kannst nicht einfach normed/density=True müssen Sie stattdessen die Gewichte für jeden Wert festlegen:

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

enter image description here

Zum Vergleich die exakt gleichen Vektoren x und y mit Standardgewichten und density=True:

enter image description here

7
jojo

Es hört sich so an, als ob Sie nur ein Balkendiagramm möchten:

Alternativ können Sie Unterzeichnungen verwenden.

3
carl

Sie sollten bins aus den von hist zurückgegebenen Werten verwenden:

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)

Two matplotlib histograms with same binning

3
Adrien Renaud

Nur für den Fall, dass Sie pandas (import pandas as pd) oder sind damit einverstanden:

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()
2
serv-inc

Diese Frage wurde bereits beantwortet, wollte aber eine weitere schnelle/einfache Problemumgehung hinzufügen, die anderen Besuchern dieser Frage helfen könnte.

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

Einige hilfreiche Beispiele sind hier für den Vergleich zwischen kde und Histogramm.

0
Solomon Vimal

Inspiriert von Solomons Antwort, aber um bei der Frage zu bleiben, die sich auf das Histogramm bezieht, ist eine saubere Lösung:

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

Stellen Sie sicher, dass Sie zuerst das größere zeichnen, andernfalls müssen Sie plt.ylim (0,0.45) einstellen, damit das größere Histogramm nicht abgeschnitten wird.

0
Sarah