362 votes

Tracer deux histogrammes sur un seul graphique avec matplotlib

J'ai créé un histogramme en utilisant des données provenant d'un fichier et aucun problème. Maintenant, je voulais superposer les données d'un autre fichier dans le même histogramme, donc je fais quelque chose comme ceci

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

mais le problème est que pour chaque intervalle, seule la barre avec la valeur la plus élevée apparaît, et l'autre est cachée. Je me demande comment je pourrais tracer les deux histogrammes en même temps avec des couleurs différentes.

601voto

joaquin Points 22450

Vous avez ici un exemple concret :

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

1 votes

Ne serait-ce pas une bonne idée d'établir pyplot.hold(True) avant de tracer, juste au cas où ?

2 votes

Je ne sais pas si hold(True) est défini dans mes paramètres de configuration de matplotlib ou si pyplot se comporte ainsi par défaut, mais pour moi le code fonctionne tel quel. Le code est extrait d'une application plus importante qui ne pose aucun problème jusqu'à présent. Quoi qu'il en soit, bonne question que je me suis déjà posée en écrivant le code.

0 votes

@joaquin : comment pourrais-je spécifier que x est bleu et que y est rouge ?

310voto

Gustavo Bezerra Points 3112

Le corrigé donne le code pour un histogramme avec des barres qui se chevauchent, mais si vous voulez que chaque barre soit côte à côte (comme je l'ai fait), essayez la variation ci-dessous :

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

Référence : http://matplotlib.org/examples/statistics/histogram_demo_multihist.html

EDIT [2018/03/16] : Mise à jour pour permettre le traçage de tableaux de différentes tailles, comme suggéré par @stochastic_zeitgeist.

0 votes

@GustavoBezerra, comment l'utiliser plt.hist pour produire un fichier pdf pour chaque histogramme ? J'ai chargé mes données en utilisant pandas.read_csv et le fichier a 36 colonnes et 100 lignes. Je voudrais donc 100 fichiers pdf.

3 votes

@Sigur C'est tout à fait hors sujet. Veuillez consulter Google ou poser une nouvelle question. Ceci semble être lié : stackoverflow.com/questions/11328958/

1 votes

@stochastic_zeitgeist Je suis d'accord avec @pasbi. J'ai utilisé votre commentaire avec un dataframe pandas car j'avais besoin de pondérations différentes en raison de nans. avec x=np.array(df.a) et y=np.array(df.b.dropna()) ça a fini par être plt.hist([x, y], weights=[np.ones_like(x)/len(x), np.ones_like(y)/len(y)])

40voto

Andrew Points 111

Dans le cas où vous avez des échantillons de tailles différentes, il peut être difficile de comparer les distributions avec un seul axe des ordonnées. Par exemple :

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

Dans ce cas, vous pouvez représenter vos deux ensembles de données sur des axes différents. Pour ce faire, vous pouvez obtenir les données de votre histogramme à l'aide de matplotlib, effacer l'axe, puis le reporter sur deux axes distincts (en déplaçant les bords des cases pour qu'ils ne se chevauchent pas) :

#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

2 votes

C'est une bonne réponse brève, mais vous devriez également ajouter comment centrer les barres sur chaque étiquette de tic-tac.

23voto

Adrien Renaud Points 701

Vous devez utiliser bins à partir des valeurs renvoyées par 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)

Two matplotlib histograms with same binning

22voto

jojo Points 777

En guise d'achèvement de La réponse de Gustavo Bezerra :

Si vous voulez chaque histogramme à normaliser ( normed pour mpl<=2.1 et density pour mpl>=3.1 ), vous ne pouvez pas simplement utiliser normed/density=True vous devez définir les pondérations pour chaque valeur :

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

A titre de comparaison, le même x et y vecteurs avec des poids par défaut et density=True :

enter image description here

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X