it-swarm.com.de

Zeichnen von Histogrammen, deren Balkenhöhen in matplotlib 1 ergeben

Ich möchte ein normalisiertes Histogramm aus einem Vektor mit matplotlib zeichnen. Ich habe folgendes versucht:

plt.hist(myarray, normed=True)

ebenso gut wie:

plt.hist(myarray, normed=1)

aber keine der beiden Optionen erzeugt eine y-Achse von [0, 1], sodass die Balkenhöhen des Histogramms 1 ergeben. Ich möchte ein solches Histogramm erstellen - wie kann ich das tun?

vielen Dank!

73
user248237

Es wäre hilfreicher, wenn Sie ein vollständigeres funktionierendes (oder in diesem Fall nicht funktionierendes) Beispiel vorlegen würden.

Ich habe folgendes versucht:

import numpy as np
import matplotlib.pyplot as plt

x = np.random.randn(1000)

fig = plt.figure()
ax = fig.add_subplot(111)
n, bins, rectangles = ax.hist(x, 50, density=True)
fig.canvas.draw()
plt.show()

Dies wird in der Tat ein Balkendiagramm-Histogramm mit einer y-Achse erzeugen, die von [0,1] Geht.

Des Weiteren denke ich, dass die Summe gemäß der Dokumentation zu hist (d. H. ax.hist? Von ipython) auch in Ordnung ist:

*normed*:
If *True*, the first element of the return Tuple will
be the counts normalized to form a probability density, i.e.,
``n/(len(x)*dbin)``.  In a probability density, the integral of
the histogram should be 1; you can verify that with a
trapezoidal integration of the probability density function::

    pdf, bins, patches = ax.hist(...)
    print np.sum(pdf * np.diff(bins))

Probieren Sie es nach den obigen Befehlen aus:

np.sum(n * np.diff(bins))

Ich erhalte wie erwartet einen Rückgabewert von 1.0. Denken Sie daran, dass normed=True Nicht bedeutet, dass die Summe der Werte an jedem Balken Einheit ist, sondern dass das Integral über den Balken Einheit ist. In meinem Fall hat np.sum(n) ungefähr 7.2767 Zurückgegeben.

42
dtlussier

Wenn Sie möchten, dass die Summe aller Balken gleich eins ist, gewichten Sie jedes Fach mit der Gesamtzahl der Werte:

weights = np.ones_like(myarray)/float(len(myarray))
plt.hist(myarray, weights=weights)

Hoffe das hilft, obwohl der Thread schon ziemlich alt ist ...

182
Carsten König

Ich weiß, dass diese Antwort zu spät ist, da die Frage auf 2010 datiert ist, aber ich bin auf diese Frage gestoßen, als ich selbst vor einem ähnlichen Problem stand. Wie bereits in der Antwort angegeben, bedeutet normed = True, dass die Gesamtfläche unter dem Histogramm gleich 1 ist, aber die Summe der Höhen ungleich 1. Ich wollte jedoch aus Gründen der physikalischen Interpretation eines Histogramms eine erstellen mit der Summe der Höhen gleich 1.

Ich habe in der folgenden Frage einen Hinweis gefunden - Python: Histogramm mit Bereich, der auf etwas anderes als 1 normalisiert ist

Es war mir jedoch nicht möglich, Balken so zu gestalten, dass sie das Feature histtype = "step" hist () imitieren. Dies hat mich umgeleitet zu: Matplotlib - Stufenhistogramm mit bereits zusammengefassten Daten

Wenn die Community es für akzeptabel hält, möchte ich eine Lösung vorschlagen, die die Ideen aus beiden oben genannten Beiträgen zusammenfasst.

import matplotlib.pyplot as plt

# Let X be the array whose histogram needs to be plotted.
nx, xbins, ptchs = plt.hist(X, bins=20)
plt.clf() # Get rid of this histogram since not the one we want.

nx_frac = nx/float(len(nx)) # Each bin divided by total number of objects.
width = xbins[1] - xbins[0] # Width of each bin.
x = np.ravel(Zip(xbins[:-1], xbins[:-1]+width))
y = np.ravel(Zip(nx_frac,nx_frac))

plt.plot(x,y,linestyle="dashed",label="MyLabel")
#... Further formatting.

Dies hat bei mir wunderbar funktioniert, obwohl mir in einigen Fällen aufgefallen ist, dass der am weitesten links liegende "Balken" oder der am weitesten rechts liegende "Balken" des Histogramms nicht durch Berühren des tiefsten Punkts der Y-Achse geschlossen wird. In einem solchen Fall wurde durch Hinzufügen eines Elements 0 am Anfang oder Ende von y das erforderliche Ergebnis erzielt.

Ich dachte nur, ich würde meine Erfahrung teilen. Vielen Dank.

18
Killer

Hier ist eine weitere einfache Lösung, die die np.histogram() -Methode verwendet.

myarray = np.random.random(100)
results, edges = np.histogram(myarray, normed=True)
binWidth = edges[1] - edges[0]
plt.bar(edges[:-1], results*binWidth, binWidth)

Sie können in der Tat überprüfen, ob die Gesamtsumme 1 ergibt mit:

> print sum(results*binWidth)
1.0
10
Yuri Brovman