Rozmiar pojemnika w Matplotlib (histogram)

149

Używam matplotlib do tworzenia histogramu.

Czy istnieje sposób, aby ręcznie ustawić rozmiar pojemników w przeciwieństwie do liczby pojemników?

Sam Creamer
źródło

Odpowiedzi:

270

Właściwie to całkiem proste: zamiast liczby pojemników możesz podać listę z granicami bin. Mogą być również rozmieszczone nierówno:

plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])

Jeśli chcesz, aby były równomiernie rozłożone, możesz po prostu użyć range:

plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))

Dodano do oryginalnej odpowiedzi

Powyższy wiersz działa tylko dla datawypełnionych liczbami całkowitymi. Jak wskazuje makrokosmos , w przypadku pływaków można użyć:

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))
CodingCat
źródło
20
zamień zakres (...) na np.arange (...), aby działał z pływakami.
macrocosme
6
jaka jest tutaj przepustowość? czy ustawiłeś tę wartość wcześniej?
UserYmY
1
Wierzę binwidth w tym przykładzie można znaleźć przez: (data.max() - data.min()) / number_of_bins_you_want. + binwidthMożna zmienić, aby po prostu 1zrobić to bardziej zrozumiałe przykładem.
Jarad
2
W nawiązaniu do doskonałego rozwiązania CodingCat powyżej, dla danych zmiennoprzecinkowych, jeśli chcesz, aby słupki histogramu były wyśrodkowane wokół całkowitych x-ticków zamiast mieć granice słupków na x-tickach, wypróbuj następujące poprawki: bins = np. Zakres (dmin - 0,5, dmax + 0,5 + binwidth, binwidth)
DaveW
3
opcja lw = 5, color = "white"lub podobna wstawia białe przerwy między słupkami
PatrickT
13

W przypadku N pojemników krawędzie przedziału są określane za pomocą listy wartości N + 1, gdzie pierwsze N ​​to dolne krawędzie, a +1 to górna krawędź ostatniego przedziału.

Kod:

from numpy import np; from pylab import *

bin_size = 0.1; min_edge = 0; max_edge = 2.5
N = (max_edge-min_edge)/bin_size; Nplus1 = N + 1
bin_list = np.linspace(min_edge, max_edge, Nplus1)

Zauważ, że linspace tworzy tablicę od min_edge do max_edge podzieloną na wartości N + 1 lub N bins

Alef
źródło
1
Należy zauważyć, że pojemniki obejmują dolną granicę i nie obejmują górnej granicy, z wyjątkiem N + 1 (ostatniego) przedziału, który obejmuje obie granice.
letnia
4

Myślę, że najłatwiejszym sposobem byłoby obliczenie minimum i maksimum posiadanych danych, a następnie obliczenie L = max - min. Następnie dzielisz Lprzez żądaną szerokość pojemnika (zakładam, że to właśnie masz na myśli przez rozmiar pojemnika) i wykorzystujesz górną granicę tej wartości jako liczbę pojemników.

Il-Bhima
źródło
dokładnie to miałem na myśli, dzięki. Zastanawiałem się tylko, czy istnieje prostszy sposób, ale wydaje się, że znajdź dzięki!
Sam Creamer
Używając okrągłych liczb, nie otrzymuję okrągłego rozmiaru pojemnika przy takim podejściu. Czy ktoś tego doświadczył?
Brad Urani
3

Lubię, gdy rzeczy dzieją się automatycznie, a pojemniki mają „ładne” wartości. Poniższe wydaje się działać całkiem dobrze.

import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
def compute_histogram_bins(data, desired_bin_size):
    min_val = np.min(data)
    max_val = np.max(data)
    min_boundary = -1.0 * (min_val % desired_bin_size - min_val)
    max_boundary = max_val - max_val % desired_bin_size + desired_bin_size
    n_bins = int((max_boundary - min_boundary) / desired_bin_size) + 1
    bins = np.linspace(min_boundary, max_boundary, n_bins)
    return bins

if __name__ == '__main__':
    data = np.random.random_sample(100) * 123.34 - 67.23
    bins = compute_histogram_bins(data, 10.0)
    print(bins)
    plt.hist(data, bins=bins)
    plt.xlabel('Value')
    plt.ylabel('Counts')
    plt.title('Compute Bins Example')
    plt.grid(True)
    plt.show()

Rezultatem są pojemniki w ładnych odstępach wielkości pojemnika.

[-70. -60. -50. -40. -30. -20. -10.   0.  10.  20.  30.  40.  50.  60.]

obliczony histogram pojemników

pay_it_forward
źródło
Dokładnie to, czego szukałem! Jednak w niektórych przypadkach n_bins jest zaokrąglane w dół ze względu na precyzję zmiennoprzecinkową. Np desired_bin_size=0.05, min_boundary=0.850, max_boundary=2.05obliczanie n_binsstaje int(23.999999999999993)która skutkuje 23 zamiast 24, a zatem jeden bin zbyt mało. Zaokrąglenie przed konwersją liczb całkowitych zadziałało dla mnie:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
M. Schlenker,
3

Używam kwantyli, aby zbiorniki były jednolite i dopasowane do próbki:

bins=df['Generosity'].quantile([0,.05,0.1,0.15,0.20,0.25,0.3,0.35,0.40,0.45,0.5,0.55,0.6,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1]).to_list()

plt.hist(df['Generosity'], bins=bins, normed=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none')

wprowadź opis obrazu tutaj

Wojciech Moszczyński
źródło
1
Świetny pomysł. Możesz zamienić listę kwantyli na np.arange(0, 1.01, 0.5)lub np.linspace(0, 1, 21). Nie ma krawędzi, ale rozumiem, że pola mają równą powierzchnię, ale inną szerokość w osi X?
Tomasz Gandor
2

Miałem ten sam problem co OP (chyba!), Ale nie mogłem sprawić, by działał w sposób określony przez Lastalda. Nie wiem, czy poprawnie zinterpretowałem pytanie, ale znalazłem inne rozwiązanie (ale prawdopodobnie jest to naprawdę zły sposób).

Tak to zrobiłem:

plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);

Który to tworzy:

obraz przedstawiający wykres histogramu utworzony w matplotlib

Tak więc pierwszy parametr w zasadzie „inicjalizuje” pojemnik - specjalnie tworzę liczbę znajdującą się między zakresem, który ustawiłem w parametrze bins.

Aby to zademonstrować, spójrz na tablicę w pierwszym parametrze ([1,11,21,31,41]) i tablicę „bins” w drugim parametrze ([0,10,20,30,40,50]) :

  • Liczba 1 (z pierwszej tablicy) mieści się w zakresie od 0 do 10 (w tablicy „bins”)
  • Liczba 11 (z pierwszej tablicy) mieści się w zakresie od 11 do 20 (w tablicy „bins”)
  • Liczba 21 (z pierwszej tablicy) mieści się w zakresie od 21 do 30 (w tablicy „bins”) itd.

Następnie używam parametru „wagi”, aby zdefiniować rozmiar każdego pojemnika. To jest tablica używana dla parametru wagi: [10,1,40,33,6].

Tak więc przedział od 0 do 10 otrzymuje wartość 10, przedział od 11 do 20 ma wartość 1, przedział 21 do 30 otrzymuje wartość 40 itd.

bluguy
źródło
3
Myślę, że masz podstawowe nieporozumienie, jak działa funkcja histogramu. Oczekuje surowych danych. W naszym przykładzie tablica danych powinna zawierać 10 wartości od 0 do 10, 1 wartość od 10 do 20 i tak dalej. Następnie funkcja sumuje ORAZ rysuje. To, co robisz powyżej, jest obejściem, ponieważ masz już sumy (które następnie wstawiasz do wykresu, niewłaściwie używając opcji „wagi”). Mam nadzieję, że to wyjaśnia pewne zamieszanie.
CodingCat
-1

Dla histogramu z całkowitymi wartościami x, których użyłem

plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))

Przesunięcie o 0,5 wyśrodkowuje pojemniki na wartościach na osi X. plt.xticksWezwanie dodaje kleszcza dla każdej liczby całkowitej.

Adversus
źródło