Istogramma usando gnuplot?

So come creare un istogramma (basta usare “con le scatole”) in gnuplot se il mio file .dat ha già i dati correttamente abbinati. C’è un modo per prendere una lista di numeri e avere gnuplot fornire un istogramma basato su intervalli e dimensioni dei raccoglitori forniti dall’utente?

sì, e il suo rapido e semplice anche se molto nascosto:

binwidth=5 bin(x,width)=width*floor(x/width) plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes 

controlla help smooth freq per vedere perché sopra rende un istogramma

per gestire gli intervalli basta impostare la variabile xrange.

Ho un paio di correzioni / aggiunte alla risposta molto utile di Born2Smile:

  1. I contenitori vuoti hanno causato l’errata estensione della scatola per il cestino adiacente nel suo spazio; evitarlo usando l’ set boxwidth binwidth
  2. Nella versione di Born2Smile, i bin sono resi centrati sul loro limite inferiore. Strettamente dovrebbero estendersi dal limite inferiore al limite superiore. Questo può essere corretto modificando la funzione bin : bin(x,width)=width*floor(x/width) + binwidth/2.0

Fai molta attenzione: tutte le risposte in questa pagina prendono implicitamente la decisione di dove inizia il binning – il bordo sinistro del bin più a sinistra, se vuoi – fuori dalle mani dell’utente. Se l’utente sta combinando una di queste funzioni per il binning dei dati con la propria decisione su dove inizia il binning (come è fatto sul blog che è collegato a sopra) le funzioni di cui sopra sono tutte errate. Con un punto di partenza arbitrario per il binning “Min”, la funzione corretta è:

 bin(x) = width*(floor((x-Min)/width)+0.5) + Min 

Puoi capire perché questo è corretto in sequenza (aiuta a disegnare alcuni scomparti e un punto da qualche parte in uno di essi). Sottrai Min dal tuo punto dati per vedere fino a che punto si trova nell’intervallo di categorizzazione. Quindi dividi per larghezza di banda in modo da lavorare efficacemente in unità di “bidoni”. Quindi “pavimento” il risultato per andare al bordo sinistro di quel raccoglitore, aggiungere 0,5 per andare al centro del contenitore, moltiplicare per la larghezza in modo da non lavorare più in unità di contenitori ma in una scala assoluta di nuovo, quindi aggiungere nuovamente l’offset Min sottratto all’inizio.

Considera questa funzione in azione:

 Min = 0.25 # where binning starts Max = 2.25 # where binning ends n = 2 # the number of bins width = (Max-Min)/n # binwidth; evaluates to 1.0 bin(x) = width*(floor((x-Min)/width)+0.5) + Min 

per esempio il valore 1.1 cade veramente nel cestino di sinistra:

  • questa funzione lo mappa correttamente al centro del contenitore di sinistra (0.75);
  • La risposta di Born2Smile, bin (x) = width * floor (x / width), la mappa in modo errato su 1;
  • La risposta di mas90, bin (x) = width * floor (x / width) + binwidth / 2.0, la mappano erroneamente a 1.5.

La risposta di Born2Smile è corretta solo se i limiti del bin si verificano in (n + 0.5) * binwidth (dove n viene eseguito su interi). La risposta di mas90 è corretta solo se i confini del contenitore si verificano in n * larghezza di banda.

Vuoi tracciare un grafico come questo? inserisci la descrizione dell'immagine qui sì? Quindi puoi dare un’occhiata al mio articolo del blog: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html

Linee chiave del codice:

 n=100 #number of intervals max=3. #max value min=-3. #min value width=(max-min)/n #interval width #function used to map a value to the intervals hist(x,width)=width*floor(x/width)+width/2.0 set boxwidth width*0.9 set style fill solid 0.5 # fill style #count and plot plot "data.dat" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb"green" notitle 

Come al solito, Gnuplot è uno strumento fantastico per tracciare grafici dall’aspetto dolce e può essere fatto per eseguire tutti i tipi di calcoli. Tuttavia , è inteso per tracciare dati piuttosto che per servire come calcolatrice ed è spesso più facile usare un programma esterno (ad esempio Octave) per eseguire calcoli più “complicati”, salvare questi dati in un file, quindi utilizzare Gnuplot per produrre il grafo. Per il problema precedente, controlla che la funzione “hist” sia Octave che usa [freq,bins]=hist(data) , quindi traccia questo in Gnuplot usando

 set style histogram rowstacked gap 0 set style fill solid 0.5 border lt -1 plot "./data.dat" smooth freq with boxes 

Ho trovato questa discussione estremamente utile, ma ho riscontrato alcuni problemi di “arrotondamento”.

Più precisamente, usando una larghezza di banda di 0.05, ho notato che, con le tecniche presentate qui sopra, i punti di dati che leggono 0.1 e 0.15 cadono nello stesso bin. Questo (ovviamente comportamento indesiderato) è molto probabilmente dovuto alla funzione “floor”.

Qui di seguito è il mio piccolo contributo per cercare di aggirare questo.

 bin(x,width,n)=x<=n*width? width*(n-1) + 0.5*binwidth:bin(x,width,n+1) binwidth = 0.05 set boxwidth binwidth plot "data.dat" u (bin($1,binwidth,1)):(1.0) smooth freq with boxes 

Questo metodo ricorsivo è per x> = 0; si potrebbe generalizzare questo con più dichiarazioni condizionali per ottenere qualcosa di ancora più generale.

Non è necessario utilizzare il metodo ricorsivo, potrebbe essere lento. La mia soluzione utilizza una funzione definita dall’utente rint instesd di instrinsic function int o floor.

 rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x) 

Questa funzione darà rint(0.0003/0.0001)=3 , mentre int(0.0003/0.0001)=floor(0.0003/0.0001)=2 .

Perché? Si prega di guardare la funzione int perl e zeri padding

Ho una piccola modifica alla soluzione di Born2Smile.

So che non ha molto senso, ma potresti volerlo per ogni evenienza. Se i tuoi dati sono interi e hai bisogno di una dimensione del contenitore mobile (magari per il confronto con un altro insieme di dati, o la densità della trama nella griglia più fine), dovrai aggiungere un numero casuale compreso tra 0 e 1 all’interno del pavimento. Altrimenti, ci saranno picchi dovuti all’errore di arrotondamento. floor(x/width+0.5) non funzionerà perché creerà pattern non allineati ai dati originali.

 binwidth=0.3 bin(x,width)=width*floor(x/width+rand(0)) 

Per quanto riguarda le funzioni di binning, non mi aspettavo il risultato delle funzioni offerte finora. Vale a dire, se la mia larghezza di banda è 0.001, queste funzioni stavano centrando i bin su 0.0005 punti, mentre io sento che è più intuitivo avere i bin centrati sui limiti di 0,001.

In altre parole, mi piacerebbe avere

 Bin 0.001 contain data from 0.0005 to 0.0014 Bin 0.002 contain data from 0.0015 to 0.0024 ... 

La funzione di binning che ho trovato è

 my_bin(x,width) = width*(floor(x/width+0.5)) 

Ecco uno script per confrontare alcune delle funzioni bin offerte a questo:

 rint(x) = (x-int(x)>0.9999)?int(x)+1:int(x) bin(x,width) = width*rint(x/width) + width/2.0 binc(x,width) = width*(int(x/width)+0.5) mitar_bin(x,width) = width*floor(x/width) + width/2.0 my_bin(x,width) = width*(floor(x/width+0.5)) binwidth = 0.001 data_list = "-0.1386 -0.1383 -0.1375 -0.0015 -0.0005 0.0005 0.0015 0.1375 0.1383 0.1386" my_line = sprintf("%7s %7s %7s %7s %7s","data","bin()","binc()","mitar()","my_bin()") print my_line do for [i in data_list] { iN = i + 0 my_line = sprintf("%+.4f %+.4f %+.4f %+.4f %+.4f",iN,bin(iN,binwidth),binc(iN,binwidth),mitar_bin(iN,binwidth),my_bin(iN,binwidth)) print my_line } 

ed ecco l’output

  data bin() binc() mitar() my_bin() -0.1386 -0.1375 -0.1375 -0.1385 -0.1390 -0.1383 -0.1375 -0.1375 -0.1385 -0.1380 -0.1375 -0.1365 -0.1365 -0.1375 -0.1380 -0.0015 -0.0005 -0.0005 -0.0015 -0.0010 -0.0005 +0.0005 +0.0005 -0.0005 +0.0000 +0.0005 +0.0005 +0.0005 +0.0005 +0.0010 +0.0015 +0.0015 +0.0015 +0.0015 +0.0020 +0.1375 +0.1375 +0.1375 +0.1375 +0.1380 +0.1383 +0.1385 +0.1385 +0.1385 +0.1380 +0.1386 +0.1385 +0.1385 +0.1385 +0.1390