Dimensione del contenitore in Matplotlib (istogramma)


149

Sto usando matplotlib per creare un istogramma.

Esiste un modo per impostare manualmente la dimensione dei contenitori anziché il numero di contenitori?

Risposte:


270

In realtà, è abbastanza semplice: al posto del numero di bin è possibile fornire un elenco con i limiti del cestino. Possono anche essere distribuiti in modo diseguale:

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

Se li vuoi distribuire equamente, puoi semplicemente usare range:

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

Aggiunto alla risposta originale

La riga sopra funziona solo per datanumeri interi. Come sottolinea il macrocosmo , per i float puoi usare:

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))

20
sostituire range (...) con np.arange (...) per farlo funzionare con float.
macrocosme,

6
qual è il binwidth qui? hai impostato quel valore prima?
UtenteYmY

1
Credo binwidth in questo esempio potrebbe essere trovato per: (data.max() - data.min()) / number_of_bins_you_want. Si + binwidthpotrebbe cambiare per 1renderlo un esempio più facilmente comprensibile.
Jarad,

2
Oltre all'eccellente soluzione di CodingCat sopra, per i dati float, se si desidera che le barre dell'istogramma siano centrate attorno ai segni di spunta interi invece di avere i limiti della barra sui segni di spunta x, provare la seguente modifica: bins = np.arange (dmin - 0.5, dmax + 0,5 + binwidth, binwidth)
DaveW

3
opzione lw = 5, color = "white"o simile inserisce spazi bianchi tra le barre
PatrickT

13

Per i bin N, i bordi del contenitore sono specificati dall'elenco dei valori N + 1 in cui il primo N indica i bordi del contenitore inferiore e il +1 indica il bordo superiore dell'ultimo cestino.

Codice:

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)

Nota che linspace produce un array da min_edge a max_edge suddiviso in valori N + 1 o N bin


1
Si noti che i bin sono comprensivi del limite inferiore ed esclusivi del limite superiore, ad eccezione del cestino N + 1 (ultimo) che include entrambi i limiti.
lukewitmer

4

Immagino che il modo più semplice sarebbe calcolare il minimo e il massimo dei dati che hai, quindi calcolare L = max - min. Quindi dividi Lper la larghezza del cestino desiderata (suppongo che questo sia ciò che intendi per dimensione del cestino) e usi il soffitto di questo valore come numero di bin.


questo è esattamente quello che avevo in mente, grazie. Mi chiedevo solo se ci fosse un modo più semplice ma questo sembra trovare grazie!
Sam Creamer,

Usando i numeri rotondi non ottengo una dimensione del cestino tondo con questo approccio. Qualcuno l'ha provato?
Brad Urani,

3

Mi piace che le cose accadano automaticamente e che i cassonetti cadano su valori "carini". Quanto segue sembra funzionare abbastanza bene.

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()

Il risultato ha bin su intervalli piacevoli delle dimensioni del cestino.

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

istogramma dei contenitori calcolati


Esattamente quello che stavo cercando! Tuttavia, in alcuni casi n_bins viene arrotondato per difetto a causa della precisione in virgola mobile. Ad esempio per desired_bin_size=0.05, min_boundary=0.850, max_boundary=2.05il calcolo dei n_binsdiviene int(23.999999999999993)cui risultati in 23 invece di 24 e quindi uno scomparto troppo pochi. Un arrotondamento prima della conversione dei numeri interi ha funzionato per me:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
M. Schlenker,

3

Uso i quantili per uniformare i contenitori e adattarli al campione:

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')

inserisci qui la descrizione dell'immagine


1
Grande idea. È possibile sostituire l'elenco di quantili con np.arange(0, 1.01, 0.5)o np.linspace(0, 1, 21). Non ci sono spigoli, ma capisco che le caselle hanno un'area uguale, ma diversa larghezza nell'asse X?
Tomasz Gandor,

2

Ho avuto lo stesso problema di OP (penso!), Ma non sono riuscito a farlo funzionare nel modo specificato da Lastalda. Non so se ho interpretato correttamente la domanda, ma ho trovato un'altra soluzione (probabilmente è comunque un modo molto brutto di farlo).

Questo è stato il modo in cui l'ho fatto:

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

Che crea questo:

immagine che mostra il grafico dell'istogramma creato in matplotlib

Quindi il primo parametro fondamentalmente "inizializza" il cestino - Sto specificatamente creando un numero compreso nell'intervallo impostato nel parametro bin.

Per dimostrarlo, guarda l'array nel primo parametro ([1,11,21,31,41]) e l'array 'bin' nel secondo parametro ([0,10,20,30,40,50]) :

  • Il numero 1 (dal primo array) è compreso tra 0 e 10 (nell'array 'bins')
  • Il numero 11 (dal primo array) è compreso tra 11 e 20 (nell'array 'bin')
  • Il numero 21 (dal primo array) è compreso tra 21 e 30 (nell'array 'bin'), ecc.

Quindi sto usando il parametro 'pesi' per definire la dimensione di ogni cestino. Questa è la matrice utilizzata per il parametro weights: [10,1,40,33,6].

Quindi al cestino da 0 a 10 viene assegnato il valore 10, al cestino da 11 a 20 viene assegnato il valore 1, al cestino da 21 a 30 viene assegnato il valore 40, ecc.


3
Penso che tu abbia un malinteso di base sul funzionamento della funzione dell'istogramma. Si aspetta dati grezzi. Quindi, nel tuo esempio, l'array di dati dovrebbe contenere 10 valori tra 0 e 10, 1 valore tra 10 e 20 e così via. Quindi la funzione esegue il riepilogo E il disegno. Quello che stai facendo sopra è una soluzione alternativa perché hai già le somme (che poi inserisci nel grafico usando in modo improprio l'opzione "pesi"). Spero che questo chiarisca un po 'di confusione.
Coding Cat

-1

Per un istogramma con valori x interi ho finito per usare

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

L'offset di 0,5 centra i bin sui valori dell'asse x. La plt.xtickschiamata aggiunge un segno di spunta per ogni numero intero.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.