Histogramme Matplotlib

107

J'ai donc un petit problème. J'ai un ensemble de données en scipy qui est déjà au format histogramme, donc j'ai le centre des bacs et le nombre d'événements par bac. Comment puis-je maintenant tracer un histogramme. J'ai essayé juste de faire

bins, n=hist()

mais ça n'a pas plu. Des recommandations?

madtowneast
la source

Réponses:

239
import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
hist, bins = np.histogram(x, bins=50)
width = 0.7 * (bins[1] - bins[0])
center = (bins[:-1] + bins[1:]) / 2
plt.bar(center, hist, align='center', width=width)
plt.show()

entrez la description de l'image ici

L'interface orientée objet est également simple:

fig, ax = plt.subplots()
ax.bar(center, hist, align='center', width=width)
fig.savefig("1.png")

Si vous utilisez des bacs personnalisés (non constants), vous pouvez transmettre le calcul des largeurs en utilisant np.diff, transmettre les largeurs à ax.baret utiliser ax.set_xtickspour étiqueter les bords des bacs :

import matplotlib.pyplot as plt
import numpy as np

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
bins = [0, 40, 60, 75, 90, 110, 125, 140, 160, 200]
hist, bins = np.histogram(x, bins=bins)
width = np.diff(bins)
center = (bins[:-1] + bins[1:]) / 2

fig, ax = plt.subplots(figsize=(8,3))
ax.bar(center, hist, align='center', width=width)
ax.set_xticks(bins)
fig.savefig("/tmp/out.png")

plt.show()

entrez la description de l'image ici

unutbu
la source
Existe-t-il un moyen de faire passer les bords du bac à l'axe des x du graphique à barres?
CMCDragonkai
@CMCDragonkai: plt.barde » widthparamètre peut accepter un objet en forme de matrice ( au lieu d'un scalaire). Vous pouvez donc utiliser à la width = np.diff(bins)place de width = 0.7 * (bins[1] - bins[0]).
unutbu le
Mais le widthréglage en lui-même ne définit que la largeur de la barre, non? Je parle des étiquettes de l'axe x (c'est-à-dire que je veux voir les bords réels du bac étant des étiquettes sur l'axe des x). Cela devrait être similaire à la façon dont plt.histfonctionne.
CMCDragonkai
2
@CMCDragonkai: Vous pouvez utiliser ax.set_xtickspour définir les xlabels. J'ai ajouté un exemple ci-dessus pour montrer ce que je veux dire.
unutbu
22

Si vous ne voulez pas de barres, vous pouvez le tracer comme ceci:

import numpy as np
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

bins, edges = np.histogram(x, 50, normed=1)
left,right = edges[:-1],edges[1:]
X = np.array([left,right]).T.flatten()
Y = np.array([bins,bins]).T.flatten()

plt.plot(X,Y)
plt.show()

histogramme

Matthias123
la source
6
Vous pouvez également utiliser ax.step.
tacaswell
12

Je sais que cela ne répond pas à votre question, mais je finis toujours sur cette page, lorsque je recherche la solution matplotlib aux histogrammes, car le simple a histogram_demoété supprimé de la page de la galerie d'exemples matplotlib.

Voici une solution qui ne nécessite pas numpyd'être importée. J'importe uniquement numpy pour générer les données xà tracer. Il repose sur la fonction histau lieu de la fonction barcomme dans la réponse de @unutbu.

import numpy as np
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)

import matplotlib.pyplot as plt
plt.hist(x, bins=50)
plt.savefig('hist.png')

entrez la description de l'image ici

Consultez également la galerie matplotlib et les exemples matplotlib .

tommy.carstensen
la source
"Voici une solution, qui ne nécessite pas de numpy" - première ligne de code importe numpy :)
Martin R.
2
@Martin R. C'est uniquement pour générer les données à tracer. Voir les lignes 4-6. Aucune utilisation de numpy.
tommy.carstensen
6

Si vous êtes prêt à utiliser pandas:

pandas.DataFrame({'x':hist[1][1:],'y':hist[0]}).plot(x='x',kind='bar')
Michael Malak
la source
27
Si vous envisagez d'utiliser, pandasvous devriez probablement inclure un lien vers leur site et un exemple plus détaillé qui explique ce qui se passe.
tacaswell
0

Je pense que cela pourrait être utile pour quelqu'un.

La fonction d'histogramme de Numpy, à mon grand désagrément (bien que, j'apprécie qu'il y ait une bonne raison à cela), renvoie les bords de chaque bac, plutôt que la valeur de la case. Bien que cela ait du sens pour les nombres à virgule flottante, qui peuvent se trouver dans un intervalle (c'est-à-dire que la valeur centrale n'est pas très significative), ce n'est pas la sortie souhaitée lorsqu'il s'agit de valeurs discrètes ou d'entiers (0, 1, 2, etc.) . En particulier, la longueur des cases renvoyées par np.histogram n'est pas égale à la longueur des comptages / densité.

Pour contourner cela, j'ai utilisé np.digitize pour quantifier l'entrée et renvoyer un nombre discret de bacs, ainsi qu'une fraction de comptage pour chaque bac. Vous pouvez facilement modifier pour obtenir le nombre entier de comptes.

def compute_PMF(data)
    import numpy as np
    from collections import Counter
    _, bins = np.histogram(data, bins='auto', range=(data.min(), data.max()), density=False)
    h = Counter(np.digitize(data,bins) - 1)
    weights = np.asarray(list(h.values())) 
    weights = weights / weights.sum()
    values = np.asarray(list(h.keys()))
    return weights, values
####

Réf:

[1] https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html

[2] https://docs.scipy.org/doc/numpy/reference/generated/numpy.digitize.html

sirgogo
la source