¿Histogtwig usando gnuplot?

Sé cómo crear un histogtwig (simplemente use “con cuadros”) en gnuplot si mi archivo .dat ya tiene datos correctamente agrupados. ¿Hay alguna manera de tomar una lista de números y hacer que gnuplot proporcione un histogtwig en función de los rangos y tamaños de espacio que el usuario proporciona?

sí, y es rápido y simple aunque muy escondido:

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

echa un vistazo a help smooth freq para ver por qué lo anterior hace un histogtwig

para hacer frente a los rangos, simplemente configure la variable de xrange.

Tengo un par de correcciones / adiciones a la muy útil respuesta de Born2Smile:

  1. Los contenedores vacíos hicieron que la caja para el contenedor adyacente se extendiera incorrectamente en su espacio; evitar esto usando set boxwidth binwidth
  2. En la versión de Born2Smile, los contenedores se representan como centrados en su límite inferior. Estrictamente, deberían extenderse desde el límite inferior al límite superior. Esto se puede corregir modificando la función bin : bin(x,width)=width*floor(x/width) + binwidth/2.0

Tenga mucho cuidado: todas las respuestas en esta página toman implícitamente la decisión de dónde comienza el binning, el borde izquierdo del contenedor más a la izquierda, si lo desea, fuera de las manos del usuario. Si el usuario combina cualquiera de estas funciones para agrupar datos con su propia decisión sobre dónde comienza el binning (como se hace en el blog al que se ha vinculado anteriormente), las funciones anteriores son todas incorrectas. Con un punto de inicio arbitrario para agrupar ‘Min’, la función correcta es:

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

Puedes ver por qué esto es correcto de forma secuencial (ayuda a dibujar algunos contenedores y un punto en algún punto de uno de ellos). Reste Min de su punto de datos para ver qué tan lejos está dentro del rango de binning. Luego divide por binwidth para que estés trabajando efectivamente en unidades de ‘bins’. Luego, ‘fondo’ el resultado para ir al borde izquierdo de ese contenedor, agregue 0.5 para ir al medio del contenedor, multiplique por el ancho para que ya no trabaje en unidades de contenedores, sino en una escala absoluta nuevamente, luego, vuelva a agregar el desplazamiento Min que resta al inicio.

Considera esta función en acción:

 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 

por ejemplo, el valor 1.1 cae realmente en el contenedor izquierdo:

  • esta función lo ubica correctamente en el centro del contenedor izquierdo (0.75);
  • La respuesta de Born2Smile, bin (x) = ancho * piso (x / ancho), lo mapea incorrectamente en 1;
  • La respuesta de mas90, bin (x) = ancho * piso (x / ancho) + binwidth / 2.0, lo mapea incorrectamente a 1.5.

La respuesta de Born2Smile solo es correcta si los límites del bin se producen en (n + 0.5) * binwidth (donde n se ejecuta sobre enteros). La respuesta de mas90 solo es correcta si los límites del contenedor se producen en n * binwidth.

¿Quieres trazar un gráfico como este? enter image description here ¿sí? Entonces puedes echarle un vistazo al artículo de mi blog: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html

Líneas clave del código:

 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 

Como de costumbre, Gnuplot es una herramienta fantástica para trazar gráficos de aspecto dulce y se puede hacer para realizar todo tipo de cálculos. Sin embargo , está pensado para trazar datos en lugar de servir como una calculadora y, a menudo, es más fácil usar un progtwig externo (por ejemplo, Octave) para hacer los cálculos más “complicados”, guardar estos datos en un archivo, luego usar Gnuplot para producir la gráfica. Para el problema anterior, compruebe que la función “hist” es Octave usando [freq,bins]=hist(data) , luego trace esto en Gnuplot usando

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

He encontrado esta discusión extremadamente útil, pero he experimentado algunos problemas de “redondeo”.

Más precisamente, usando un ancho de banda de 0.05, he notado que, con las técnicas presentadas aquí arriba, los puntos de datos que leen 0.1 y 0.15 caen en el mismo contenedor. Esto (comportamiento obviamente no deseado) se debe probablemente a la función “piso”.

De ahora en adelante es mi pequeña contribución para tratar de eludir esto.

 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 

Este método recursivo es para x> = 0; uno podría generalizar esto con más declaraciones condicionales para obtener algo aún más general.

No necesitamos usar un método recursivo, puede ser lento. Mi solución está utilizando una función definida por el usuario rint instesd de la función intrínseca int o floor.

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

Esta función dará rint(0.0003/0.0001)=3 , mientras que int(0.0003/0.0001)=floor(0.0003/0.0001)=2 .

¿Por qué? Por favor mira la función int de Perl y los ceros de relleno

Tengo una pequeña modificación en la solución de Born2Smile.

Sé que eso no tiene mucho sentido, pero es posible que lo desee por las dudas. Si sus datos son enteros y necesita un tamaño de contenedor flotante (tal vez para comparar con otro conjunto de datos, o densidad de trazado en una cuadrícula más fina), necesitará agregar un número aleatorio entre 0 y 1 dentro del piso. De lo contrario, habrá picos debido al error de redondeo. floor(x/width+0.5) no funcionará porque creará un patrón que no es verdadero para los datos originales.

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

Con respecto a las funciones de binning, no esperaba el resultado de las funciones ofrecidas hasta ahora. A saber, si mi ancho de banda es 0.001, estas funciones estaban centrando los contenedores en 0.0005 puntos, mientras que creo que es más intuitivo tener los contenedores centrados en los límites de 0.001.

En otras palabras, me gustaría tener

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

La función de binning que se me ocurrió es

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

Aquí hay un script para comparar algunas de las funciones de bin ofrecidas a esta:

 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 } 

y aquí está la salida

  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 
    Intereting Posts