Histogramme avec gnuplot?
je sais comment créer un histogramme (il suffit d'utiliser "avec des cases") dans gnuplot si mon .dat fichier a déjà correctement binned les données. Est-il possible de prendre une liste de numéros et ont gnuplot fournir un histogramme basé sur les gammes et tailles de bac fournit de l'utilisateur?
9 réponses
oui, et son rapide et simple bien que très caché:
binwidth=5
bin(x,width)=width*floor(x/width)
plot 'datafile' using (bin(,binwidth)):(1.0) smooth freq with boxes
check out help smooth freq
pour voir pourquoi ci-dessus fait un histogramme
pour gérer les plages, il suffit de définir la variable xrange.
j'ai quelques corrections/ajouts à la réponse très utile de Born2Smile:
- des bacs vides ont causé l'extension incorrecte de la boîte pour la boîte adjacente dans son espace; éviter cela en utilisant
set boxwidth binwidth
- dans la version de Born2Smile, les bacs sont centrés sur leur limite inférieure. Elles doivent s'étendre strictement de la limite inférieure à la limite supérieure. Ceci peut être corrigé en modifiant la fonction
bin
:bin(x,width)=width*floor(x/width) + binwidth/2.0
soyez très prudent: toutes les réponses sur cette page prennent implicitement la décision de l'endroit où le binning commence - le bord gauche de la poubelle la plus à gauche, si vous voulez-hors des mains de l'utilisateur. Si l'utilisateur combine l'une de ces fonctions pour le stockage de données avec sa propre décision sur l'endroit où le stockage commence (comme c'est fait sur le blog qui est lié ci-dessus) les fonctions ci-dessus sont toutes incorrectes. Avec un point de départ arbitraire pour binning 'Min', la fonction correcte est:
bin(x) = width*(floor((x-Min)/width)+0.5) + Min
vous pouvez voir pourquoi ceci est correct séquentiellement (cela aide à dessiner quelques bacs et un point quelque part dans l'un d'eux). Soustrayez Min de votre point de données pour voir la distance dans la gamme de binning il est. Puis divisez par binwidth de sorte que vous travaillez efficacement dans les unités de 'bins'. Puis 'plancher' le résultat pour aller au bord gauche de cette corbeille, ajouter 0.5 pour aller au milieu de la corbeille, multiplier par la largeur de sorte que vous ne travaillez plus en unités de bacs, mais en une échelle absolue de nouveau, puis finalement ajouter sur L'offset Min que vous avez soustrait au début.
Considérer cette fonction dans l'action:
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
p.ex. la valeur 1.1 tombe vraiment dans la case de gauche:
- cette fonction la place correctement au centre du bac de gauche (0,75);
- Born2Smile réponse, bin(x)=largeur*floor(x/largeur), à tort cartes 1;
- mas90 de l' réponse, bin(x)=largeur*floor(x/largeur) + binwidth/2.0, mal de cartes à 1.5.
Born2Smile la réponse est correcte uniquement si le bac limites se produire à (n+0.5)*binwidth (où n fonctionne sur les entiers). la réponse de mas90 n'est correcte que si les limites de bin se produisent à n*binwidth.
voulez-vous tracer un graphique comme celui-ci? oui? Alors vous pouvez jeter un oeil à mon article de blog: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html
lignes clés du code:
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(,width)):(1.0) smooth freq w boxes lc rgb"green" notitle
comme d'habitude, Gnuplot est un outil fantastique pour tracer des graphiques doux et il peut être fait pour effectuer toutes sortes de calculs. cependant , il est destiné à tracer des données plutôt que de servir de calculatrice et il est souvent plus facile d'utiliser un programme externe (par exemple Octave) pour faire les calculs plus "compliqués", enregistrer ces données dans un fichier, puis utiliser Gnuplot pour produire le graphe. Pour le problème ci-dessus, vérifier la fonction" hist " est Octave en utilisant [freq,bins]=hist(data)
, puis tracez ceci dans Gnuplot en utilisant
set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
j'ai trouvé cette discussion extrêmement utile, mais j'ai éprouvé quelques problèmes d'arrondissement.
plus précisément, en utilisant un binwidth de 0.05, j'ai remarqué que, avec les techniques présentées ci-dessus, les points de données qui lisent 0.1 et 0.15 tombent dans le même bin. Ce comportement (évidemment indésirable) est très probablement dû à la fonction "plancher".
, Ci-après est ma petite contribution pour essayer de contourner cela.
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(,binwidth,1)):(1.0) smooth freq with boxes
cette méthode récursive est pour x >=0; on pourrait la généraliser avec des énoncés plus conditionnels pour obtenir quelque chose d'encore plus général.
Nous n'avons pas besoin d'utiliser la méthode récursive, il peut être lent. Ma solution est d'utiliser une fonction définie par l'utilisateur rint instesd de fonction instrinsic int ou plancher.
rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x)
cette fonction donnera rint(0.0003/0.0001)=3
, tandis que int(0.0003/0.0001)=floor(0.0003/0.0001)=2
.
pourquoi? S'il vous plaît regarder fonction Perl int et zéros de remplissage
j'ai une petite modification à apporter à la solution de Born2Smile.
je sais que cela n'a pas beaucoup de sens, mais vous pouvez le vouloir juste au cas où. Si vos données sont entières et vous avez besoin d'une taille de la cellule flottante (peut-être pour la comparaison avec un autre ensemble de données, ou la densité de parcelle dans une grille plus fine), vous aurez besoin d'ajouter un nombre aléatoire entre 0 et 1 à l'intérieur du plancher. Dans le cas contraire, il y aura des pointes dues à l'erreur d'arrondi. floor(x/width+0.5)
ne va pas faire parce qu'il va créer un modèle qui n'est pas vrai aux données originales.
binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))
en ce qui concerne les fonctions de binning, Je ne m'attendais pas au résultat des fonctions offertes jusqu'à présent. A savoir, si ma binwidth est de 0.001, ces fonctions centraient les bacs sur 0.0005 points, alors que je pense qu'il est plus intuitif d'avoir les bins centrés sur 0.001 limites.
En d'autres termes, j'aimerais avoir
Bin 0.001 contain data from 0.0005 to 0.0014
Bin 0.002 contain data from 0.0015 to 0.0024
...
la fonction de binning que j'ai inventé est
my_bin(x,width) = width*(floor(x/width+0.5))
voici un script pour comparer des fonctions bin offertes à celui-ci:
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
}
et voici la sortie
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