Jak wykreślić histogram za pomocą Matplotlib w Pythonie z listą danych?

102

Próbuję wykreślić histogram za pomocą matplotlib.hist()funkcji, ale nie wiem, jak to zrobić.

Mam listę

probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]

oraz lista nazwisk (ciągi znaków).

Jak ustawić prawdopodobieństwo jako wartość y każdego słupka i nazwać je jako wartości x?

DataVizGuys
źródło

Odpowiedzi:

175

Jeśli chcesz mieć histogram, nie musisz dołączać żadnych `` nazw '' do wartości x, ponieważ na osi x miałbyś pojemniki z danymi:

import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
np.random.seed(42)
x = np.random.normal(size=1000)
plt.hist(x, density=True, bins=30)  # `density=False` would make counts
plt.ylabel('Probability')
plt.xlabel('Data');

wprowadź opis obrazu tutaj

Możesz ulepszyć swój histogram dzięki PDFlinijce, tytułom i legendzie:

import scipy.stats as st
plt.hist(x, density=True, bins=30, label="Data")
mn, mx = plt.xlim()
plt.xlim(mn, mx)
kde_xs = np.linspace(mn, mx, 301)
kde = st.gaussian_kde(x)
plt.plot(kde_xs, kde.pdf(kde_xs), label="PDF")
plt.legend(loc="upper left")
plt.ylabel('Probability')
plt.xlabel('Data')
plt.title("Histogram");

wprowadź opis obrazu tutaj

Jeśli jednak masz ograniczoną liczbę punktów danych, jak w OP, wykres słupkowy miałby większy sens, aby przedstawić dane (wtedy możesz dołączyć etykiety do osi x):

x = np.arange(3)
plt.bar(x, height=[1,2,3])
plt.xticks(x, ['a','b','c'])

wprowadź opis obrazu tutaj

Sergey Bushmanov
źródło
4
Pamiętaj, w Pythonie nie ma średników na końcu linii!
Toad22222
12
@ Toad22222 To jest fragment z komórki notebooka Ipython. Spróbuj wykonać to bez średnika i zobacz różnicę. Wszystkie fragmenty kodu, które publikuję na SO, działają idealnie na moim komputerze.
Sergey Bushmanov
3
Jeśli zastanawiasz się nad średnikiem używanym przez Siergieja, zobacz tutaj i # 16 tutaj, aby dowiedzieć się, jak średnik jest używany w komórkach notatników Jupyter (dawniej notatników IPython) podczas kreślenia w celu pominięcia tekstu o obiekcie wykresu.
Wayne
20

Jeśli jeszcze nie zainstalowałeś matplotlib, po prostu wypróbuj polecenie.

> pip install matplotlib

Import biblioteki

import matplotlib.pyplot as plot

Dane histogramu:

plot.hist(weightList,density=1, bins=20) 
plot.axis([50, 110, 0, 0.06]) 
#axis([xmin,xmax,ymin,ymax])
plot.xlabel('Weight')
plot.ylabel('Probability')

Wyświetl histogram

plot.show()

A wynik jest taki:

wprowadź opis obrazu tutaj

Niraj
źródło
2
Linia plot.axis ([50, 110, 0, 0,06]) 'jest w tym przykładzie bezużyteczna. Poza tym, ponieważ trudno koduje obszar wykresu, aby pokazać, jeśli twoje dane nie mieszczą się w nim całkowicie, możesz być zdezorientowany, dlaczego nie są one wyświetlane poprawnie.
typhon04
10

Chociaż wydaje się, że pytanie to wymaga wykreślenia histogramu za pomocą matplotlib.hist()funkcji, prawdopodobnie nie można tego zrobić przy użyciu tego samego, co druga część pytania wymaga użycia danych prawdopodobieństw jako wartości y słupków i nazwisk (łańcuchów) jako wartości x.

Zakładam przykładową listę nazwisk odpowiadającą podanym prawdopodobieństwom, aby narysować fabułę. Dla danego problemu służy tutaj prosty wykres słupkowy. Można użyć następującego kodu:

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
names = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name7', 'name8', 'name9',
'name10', 'name11', 'name12', 'name13'] #sample names
plt.bar(names, probability)
plt.xticks(names)
plt.yticks(probability) #This may be included or excluded as per need
plt.xlabel('Names')
plt.ylabel('Probability')
Shayan Shafiq
źródło
5

Jest to stare pytanie, ale żadna z poprzednich odpowiedzi nie dotyczyła prawdziwego problemu, tj. Faktu, że problem dotyczy samego pytania.

Po pierwsze, jeśli prawdopodobieństwa zostały już obliczone, tj. Zagregowane dane histogramu są dostępne w znormalizowany sposób, to prawdopodobieństwa powinny sumować się do 1. Oczywiście nie mają, a to oznacza, że ​​coś tu jest nie tak, czy to z terminologią, czy z danymi lub w sposobie zadawania pytania.

Po drugie, fakt, że etykiety są dostarczane (a nie przedziały), normalnie oznaczałby, że prawdopodobieństwa są kategoryczną zmienną odpowiedzi - a użycie wykresu słupkowego do wykreślenia histogramu jest najlepsze (lub pewne zhakowanie metody hist wykresu pyplota), Odpowiedź Shayana Shafiqa zawiera kod.

Jednak patrz kwestia 1, te prawdopodobieństwa nie są poprawne i użycie wykresu słupkowego w tym przypadku jako „histogramu” byłoby błędne, ponieważ z jakiegoś powodu nie opowiada on historii o rozkładzie jednowymiarowym (być może klasy nakładają się i obserwacje są liczone wielokrotnie razy?) i takiego wykresu nie należy w tym przypadku nazywać histogramem.

Histogram jest z definicji graficzną reprezentacją rozkładu zmiennej jednowymiarowej (patrz https://www.itl.nist.gov/div898/handbook/eda/section3/histogra.htm , https://en.wikipedia.org/wiki / Histogram) i jest tworzony poprzez rysowanie słupków o rozmiarach reprezentujących liczebności lub częstości obserwacji w wybranych klasach interesującej nas zmiennej. Jeśli zmienna jest mierzona w skali ciągłej, klasy te są przedziałami (przedziałami). Ważną częścią procedury tworzenia histogramu jest dokonanie wyboru, w jaki sposób pogrupować (lub zachować bez grupowania) kategorie odpowiedzi dla zmiennej kategorialnej lub jak podzielić dziedzinę możliwych wartości na przedziały (gdzie umieścić granice bin) dla ciągłej zmienna typu. Wszystkie obserwacje należy przedstawić i każdą tylko raz na wykresie. Oznacza to, że suma rozmiarów słupków powinna być równa całkowitej liczbie obserwacji (lub ich powierzchni w przypadku zmiennych szerokości, co jest rzadziej stosowane). Lub, jeśli histogram jest znormalizowany, wszystkie prawdopodobieństwa muszą sumować się do 1.

Jeśli same dane są listą „prawdopodobieństw” jako odpowiedzi, tj. Obserwacje są wartościami prawdopodobieństwa (czegoś) dla każdego obiektu badania, wówczas najlepszą odpowiedzią jest po prostu plt.hist(probability)być może opcja binningu, a użycie już dostępnych etykiet x jest podejrzany.

Wtedy wykres słupkowy nie powinien być używany jako histogram, ale raczej po prostu

import matplotlib.pyplot as plt
probability = [0.3602150537634409, 0.42028985507246375, 
  0.373117033603708, 0.36813186813186816, 0.32517482517482516, 
  0.4175257731958763, 0.41025641025641024, 0.39408866995073893, 
  0.4143222506393862, 0.34, 0.391025641025641, 0.3130841121495327, 
  0.35398230088495575]
plt.hist(probability)
plt.show()

z wynikami

wprowadź opis obrazu tutaj

matplotlib w takim przypadku pojawia się domyślnie z następującymi wartościami histogramu

(array([1., 1., 1., 1., 1., 2., 0., 2., 0., 4.]),
 array([0.31308411, 0.32380469, 0.33452526, 0.34524584, 0.35596641,
        0.36668698, 0.37740756, 0.38812813, 0.39884871, 0.40956928,
        0.42028986]),
 <a list of 10 Patch objects>)

wynikiem jest krotka tablic, pierwsza tablica zawiera zliczenia obserwacji, czyli to, co zostanie pokazane na osi y wykresu (sumują się do 13, całkowita liczba obserwacji), a druga tablica to granice przedziałów dla x -oś.

Można sprawdzić, czy są równo rozstawione,

x = plt.hist(probability)[1]
for left, right in zip(x[:-1], x[1:]):
  print(left, right, right-left)

wprowadź opis obrazu tutaj

Lub, na przykład, dla 3 pojemników (moja ocena wymaga 13 obserwacji), można by otrzymać ten histogram

plt.hist(probability, bins=3)

wprowadź opis obrazu tutaj

z danymi wykresu będącymi „za kratkami”

wprowadź opis obrazu tutaj

Autor pytania musi sprecyzować, jakie znaczenie ma lista wartości „prawdopodobieństwa” - czy „prawdopodobieństwo” to tylko nazwa zmiennej odpowiedzi (w takim razie dlaczego są gotowe x-etykiety na histogram, to nie ma sensu ), czy też lista wartości prawdopodobieństw obliczonych na podstawie danych (wtedy fakt, że nie sumują się one do 1, nie ma sensu).

predmod
źródło
4

Jest to bardzo okrągły sposób, ale jeśli chcesz zrobić histogram, na którym znasz już wartości bin, ale nie masz danych źródłowych, możesz użyć np.random.randintfunkcji do wygenerowania prawidłowej liczby wartości w zakresie każdego bin dla funkcji hist do wykreślenia, na przykład:

import numpy as np
import matplotlib.pyplot as plt

data = [np.random.randint(0, 9, *desired y value*), np.random.randint(10, 19, *desired y value*), etc..]
plt.hist(data, histtype='stepfilled', bins=[0, 10, etc..])

jeśli chodzi o etykiety, możesz wyrównać x znaczników z pojemnikami, aby uzyskać coś takiego:

#The following will align labels to the center of each bar with bin intervals of 10
plt.xticks([5, 15, etc.. ], ['Label 1', 'Label 2', etc.. ])
Connor Wilmers
źródło