Chciałbym wykreślić znormalizowany histogram z wektora za pomocą matplotlib. Próbowałem następujących rzeczy:
plt.hist(myarray, normed=True)
jak również:
plt.hist(myarray, normed=1)
ale żadna z opcji nie tworzy osi y z [0, 1] takiej, że wysokości słupków histogramu sumują się do 1. Chciałbym stworzyć taki histogram - jak mam to zrobić?
Odpowiedzi:
Byłoby bardziej pomocne, gdybyś przedstawił bardziej kompletny działający (lub w tym przypadku niedziałający) przykład.
Próbowałem następujących rzeczy:
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()
Spowoduje to rzeczywiście utworzenie histogramu wykresu słupkowego z osią Y biegnącą od
[0,1]
.Ponadto, zgodnie z
hist
dokumentacją (tj.ax.hist?
Zipython
), myślę, że suma też jest w porządku:*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))
Próbując tego po poleceniach powyżej:
Otrzymuję wartość zwrotu
1.0
zgodnie z oczekiwaniami. Pamiętaj, żenormed=True
nie oznacza to, że suma wartości na każdym słupku będzie równa jedności, ale zamiast całki po słupkach jest jednością. W moim przypadkunp.sum(n)
wrócił ok7.2767
.źródło
Jeśli chcesz, aby suma wszystkich słupków była równa jedności, zważ każdy przedział przez całkowitą liczbę wartości:
Mam nadzieję, że to pomoże, chociaż wątek jest dość stary ...
Uwaga dla Pythona 2.x: dodaj rzutowanie do
float()
dla jednego z operatorów dzielenia, ponieważ w przeciwnym razie skończysz z zerami z powodu dzielenia liczb całkowitychźródło
array_like
zamiast numpy tablicy trzeba będzie oddanychlen(myarray)
dofloat
.Wiem, że odpowiedź jest za późno, biorąc pod uwagę, że pytanie pochodzi z 2010 r., Ale natknąłem się na to pytanie, ponieważ sam miałem podobny problem. Jak już stwierdzono w odpowiedzi, normed = True oznacza, że całkowita powierzchnia pod histogramem jest równa 1, ale suma wysokości nie jest równa 1. Jednak chciałem, dla wygody fizycznej interpretacji histogramu, zrobić jeden o sumie wysokości równej 1.
Znalazłem wskazówkę w pytaniu - Python: Histogram z obszarem znormalizowanym do czegoś innego niż 1
Nie udało mi się jednak znaleźć sposobu, aby słupki naśladowały funkcję histtype = "step" hist (). To przekierowało mnie do: Matplotlib - histogram schodkowy z już skategoryzowanymi danymi
Jeśli społeczność uzna to za możliwe, chciałbym przedstawić rozwiązanie, które syntetyzuje pomysły z obu powyższych postów.
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.
To zadziałało wspaniale dla mnie, chociaż w niektórych przypadkach zauważyłem, że skrajny lewy słupek lub skrajny prawy słupek histogramu nie zamyka się, dotykając najniższego punktu osi Y. W takim przypadku dodanie elementu 0 na początku lub na końcu y przyniosło wymagany rezultat.
Pomyślałem, że podzielę się swoim doświadczeniem. Dziękuję Ci.
źródło
Oto kolejne proste rozwiązanie przy użyciu
np.histogram()
metody.myarray = np.random.random(100) results, edges = np.histogram(myarray, normed=True) binWidth = edges[1] - edges[0] plt.bar(edges[:-1], results*binWidth, binWidth)
Rzeczywiście możesz sprawdzić, czy suma sumuje się do 1 za pomocą:
> print sum(results*binWidth) 1.0
źródło