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.