Histogramm richtig normieren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
PhilipLane
User
Beiträge: 7
Registriert: Freitag 12. Dezember 2014, 11:11

Hallo Leute,

ich habe leider ein Problem damit, meine Histogramme zu normieren.
Was bei einem Parametersatz klappt, klappt leider bei dem anderen nicht und umgekehrt und
alles was ich im Internet so finde, scheint mir nicht wirklich zu helfen.

Was genau habe ich vor?
Ich möchte ein Array von Zufallszahlen (nach einer beliebigen Verteilung) als Histogramm ausgeben und
zwar derart, dass auf der y-Achse nicht die absoluten, sondern die relativen Häufigkeiten aufgetragen werden.

Minimalbeispiel:

Code: Alles auswählen

Array1 = numpy.random.triangular(10,15,20 , size=10**6)
Array2 = numpy.random.triangular(14.995,15,15.005 , size=10**6)

### PLOT 1 ###
plt.hist(Array1 ,bins = 55, normed=True, cumulative=False)
plt.title('Wahrscheinlichkeitsverteilung')
plt.xlabel('Werte')
plt.ylabel("Wahrscheinlichkeit")
plt.show()

### PLOT 2 ###
plt.hist(Array2 ,bins = 55, normed=True, cumulative=False)
plt.title('Wahrscheinlichkeitsverteilung')
plt.xlabel('Werte')
plt.ylabel("Wahrscheinlichkeit")
plt.show()

### PLOT 3 ###
weights = numpy.ones_like(Array1)/len(Array1)
plt.hist(Array1, weights=weights, bins = 55, cumulative=False, normed=False)
plt.show()

### PLOT 4 ###
weights = numpy.ones_like(Array2)/len(Array2)
plt.hist(Array2, weights=weights, bins = 55, cumulative=False, normed=False)
plt.show()
Bei Plot 1 funktioniert alles einwandfrei. Der Maximalwert hat eine Wahrscheinlichkeit von 0.2
und wenn man den Flächeninhalt A = p_max*(b-a)/2 = 0.2*10/2 = 1 berechnet, dann sieht man
auch, dass hier alles stimmt.

Dieselbe Methode funktioniert aber nicht mehr, wenn ich dieselbe Verteilungsform mit anderen Parametern
benutze; dies sieht man bei Plot 2. Dort reichen die Werte der y-Achse trotz Normierung bis 200. Die Fläche
ist dennoch insgesamt A= 200* 0,01 / 2 = 1. Dennoch kann die relative Häufigkeit nicht 200% sein.

Ich habe bei Stack eine zweite Methode gefunden, diese sind dann in Plot 3 und 4 dargestellt.
Dort erhalten wir bei BEIDEN Histogrammen die maximale Wahrscheinlichkeit von 0.035, was allerdings wegen
der unterschiedlichen Intervallbreite nicht sein. Die Fläche unter Plot 3 beträgt auch nur A=0,175 und bei Plot 4
A=0.00175. Das heißt, dass in keinem Fall die richtigen relativen Häufigkeiten angezeigt werden. Wenn ich hier normed=True
angebe, dann erhalte ich das gleiche Ergebnis wie in Plot 1 und 2.

Mit cumulative habe ich versucht, die Normierung der Verteilungen zu überprüfen, aber dies liefert mir für jede der Verteilungen die Maximalfläche von 1,
was man durch nachrechnen leicht widerlegen kann.

Gibt es eine Methode, um die korrekten relativen Häufigkeiten anzuzeigen und zwar für alle Parameter?
Die Option normed=True scheint dies ja nicht zu leisten. Ich sitze schon seit zwei Tagen an dem Problem und
-wie schon gesagt- ich habe bislang im Internet nichts gefunden, was mir helfen konnte!

Danke schon einmal Im Voraus!
LG, Kevin
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Wenn du die normierten Häufigkeiten haben willst, dann musst du diese einfach berechnen. Summiere alle Elemente des Arrays, und dividiere das Array durch die Summe. Fertig.
Das Leben ist wie ein Tennisball.
PhilipLane
User
Beiträge: 7
Registriert: Freitag 12. Dezember 2014, 11:11

EyDu hat geschrieben:Wenn du die normierten Häufigkeiten haben willst, dann musst du diese einfach berechnen. Summiere alle Elemente des Arrays, und dividiere das Array durch die Summe. Fertig.
Das ergibt ja leider auch nicht das richtige Ergebnis.

Code: Alles auswählen

Array1 = numpy.random.triangular(10,15,20 , size=10**6)
NewArray1 = Array1 / numpy.sum(Array1)

plt.hist(NewArray1 ,bins = 55, normed=True)
plt.title('Wahrscheinlichkeitsverteilung')
plt.xlabel('Werte')
plt.ylabel("Wahrscheinlichkeit")
plt.show()
Liefert mir auf der y-Achse Werte weit über 35000.

Das liegt daran, dass ich auf die Häufigkeiten direkt nicht zugreifen kann (oder nicht weiß, wie es geht).
Das Array selbst durch die Summe der Elemente zu dividieren, ergibt ja keine relative Häufigkeit, sondern nur andere Werte...
Ich müsste wohl eher die Häufigkeiten durch die Anzahl der Elemente dividieren, als das Array durch die Summe der Elemente selbst.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ach so, jetzt sehe ich erst, dass du das Histogramm nicht erst erstellst, sondern direkt darstellst. Schau dir mal den weight-Parameter der hist-Funktion an. Damit kannst du jedem Element das Gewicht 1/n zuweisen. Die np.ones_like-Funktion ist in diesem Fall sehr nützlich.
Das Leben ist wie ein Tennisball.
PhilipLane
User
Beiträge: 7
Registriert: Freitag 12. Dezember 2014, 11:11

Das habe ich in Plot 3 und 4 bereits getan; das war ja auch der Tipp bei Stack.

Leider sind die Wahrscheinlichkeiten, die ich dort erhalte, nicht korrekt; die Fläche des Histogramms entspricht nicht eins.

Wenn ich dann wieder das Histogramm normiere, sodass die Fläche eins wird, verändern sich die Werte der y-Achse wieder.

:K

Ich bin momentan echt ratlos!
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

@PhilipLane: was ist die Fläche eines Histogramms?
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Probier das mal

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt

a = np.random.triangular(10,15,20 , size=1.e6)
hist_int, bin_edges = np.histogram(a, bins=50)

hist_float = np.array(hist_int, dtype=np.float64) / hist_int.sum()
bins = (bin_edges[:-1] + bin_edges[1:])/2
width = bin_edges[1]-bin_edges[0]

plt.figure()
plt.bar(bins, hist_float, width=width)
plt.show()
Wenn Dir der Code nicht klar ist, dann setze die Werte für size und für bins soweit runter, dass Du Dir alle Arrays schön ausgeben und ansehen kannst:

Code: Alles auswählen

a = np.random.triangular(10,15,20 , size=20)
hist_int, bin_edges = np.histogram(a, bins=5)
a fool with a tool is still a fool, www.magben.de, YouTube
Benutzeravatar
MagBen
User
Beiträge: 799
Registriert: Freitag 6. Juni 2014, 05:56
Wohnort: Bremen
Kontaktdaten:

Und so gehts mit pyplot.hist

Code: Alles auswählen

import numpy as np
import matplotlib.pyplot as plt

a_size = 1.e6
a = np.random.triangular(10,15,20 , size=a_size)

plt.figure()
plt.hist(a, bins=50, weights=np.ones(a_size)/a_size)
plt.show()
a fool with a tool is still a fool, www.magben.de, YouTube
Antworten