utilidad de línea de comandos para imprimir estadísticas de números en Linux

A menudo me encuentro con un archivo que tiene un número por línea. Termino importándolo en excel para ver cosas como mediana, desviación estándar, etc.

¿Hay una utilidad de línea de comandos en Linux para hacer lo mismo? Por lo general, necesito encontrar la desviación promedio, mediana, mínima, máxima y estándar.

Esto es muy sencillo con R. Para un archivo que se ve así:

 1 2 3 4 5 6 7 8 9 10 

Utilizar esta:

 R -q -e "x < - read.csv('nums.txt', header = F); summary(x); sd(x[ , 1])" 

Para obtener esto:

  V1 Min. : 1.00 1st Qu.: 3.25 Median : 5.50 Mean : 5.50 3rd Qu.: 7.75 Max. :10.00 [1] 3.02765 

Editar para agregar un par de comentarios aclaratorios (porque volví a esto y no recuerdo algunos de los fundamentos):

  • El indicador -q silencia la licencia de inicio de R y ayuda a la salida
  • La bandera -e le dice a R que pasará una expresión de la terminal
  • x es un data.frame - una tabla, básicamente. Es una estructura que admite múltiples vectores / columnas de datos, lo cual es un poco peculiar si solo estás leyendo en un solo vector. Esto tiene un impacto en las funciones que puede usar.
  • Algunas funciones, como summary() , naturalmente acomodan data.frames . Si x tuviera múltiples campos, summary() proporcionaría las estadísticas descriptivas anteriores para cada uno.
  • Pero sd() solo puede tomar un vector a la vez, por lo que indico x para ese comando ( x[ , 1] devuelve la primera columna de x ). Puede usar apply(x, MARGIN = 2, FUN = sd) para obtener las SD de todas las columnas.

Usando “st” ( https://github.com/nferraz/st )

 $ st numbers.txt N min max sum mean stddev 10 1 10 55 5.5 3.02765 

O:

 $ st numbers.txt --transpose N 10 min 1 max 10 sum 55 mean 5.5 stddev 3.02765 

(DESCARGO DE RESPONSABILIDAD: escribí esta herramienta :))

Para el promedio, la mediana y la desviación estándar, puede usar awk . Por ejemplo, lo siguiente imprimirá el promedio:

 awk '{a+=$1} END{print a/NR}' myfile 

( NR es una variable awk para el número de registros, $1 significa el primer argumento (separado por espacios) de la línea ( $0 sería la línea completa, que también funcionaría aquí pero en principio sería menos segura, aunque para el cálculo probablemente solo tomaría el primer argumento de todos modos) y END significa que los siguientes comandos se ejecutarán después de haber procesado el archivo completo (uno también podría haber inicializado a a 0 en una instrucción BEGIN{a=0} )).

Para el min / max, puede pipe sort y head / tail :

 sort -n myfile | head -n1 sort -n myfile | tail -n1 

La herramienta Ya que se puede usar para calcular estadísticas y ver la distribución en modo ASCII es ministat . Es una herramienta de FreeBSD, pero también está empaquetada para distribución popular de Linux como Debian / Ubuntu.

Ejemplo de uso:

 $ cat test.log Handled 1000000 packets.Time elapsed: 7.575278 Handled 1000000 packets.Time elapsed: 7.569267 Handled 1000000 packets.Time elapsed: 7.540344 Handled 1000000 packets.Time elapsed: 7.547680 Handled 1000000 packets.Time elapsed: 7.692373 Handled 1000000 packets.Time elapsed: 7.390200 Handled 1000000 packets.Time elapsed: 7.391308 Handled 1000000 packets.Time elapsed: 7.388075 $ cat test.log| awk '{print $5}' | ministat -w 74 x  +--------------------------------------------------------------------------+ | x | |xx xx xxx| | |__________________________A_______M_________________| | +--------------------------------------------------------------------------+ N Min Max Median Avg Stddev x 8 7.388075 7.692373 7.54768 7.5118156 0.11126122 

Sí, se llama perl
y aquí hay una línea concisa:

 perl -e 'use List::Util qw(max min sum); @a=();while(<>){$sqsum+=$_*$_; push(@a,$_)}; $n=@a;$s=sum(@a);$a=$s/@a;$m=max(@a);$mm=min(@a);$std=sqrt($sqsum/$n-($s/$n)*($s/$n));$mid=int @a/2;@srtd=sort @a;if(@a%2){$med=$srtd[$mid];}else{$med=($srtd[$mid-1]+$srtd[$mid])/2;};print "records:$n\nsum:$s\navg:$a\nstd:$std\nmed:$med\max:$m\min:$mm";' 

Ejemplo

 $ cat tt 1 3 4 5 6.5 7. 2 3 4 

Y el comando

 cat tt | perl -e 'use List::Util qw(max min sum); @a=();while(<>){$sqsum+=$_*$_; push(@a,$_)}; $n=@a;$s=sum(@a);$a=$s/@a;$m=max(@a);$mm=min(@a);$std=sqrt($sqsum/$n-($s/$n)*($s/$n));$mid=int @a/2;@srtd=sort @a;if(@a%2){$med=$srtd[$mid];}else{$med=($srtd[$mid-1]+$srtd[$mid])/2;};print "records:$n\nsum:$s\navg:$a\nstd:$std\nmed:$med\max:$m\min:$mm";' records:9 sum:35.5 avg:3.94444444444444 std:1.86256162380447 med:4 max:7. min:1 

data_hacks es una utilidad de línea de comandos de Python para estadísticas básicas.

El primer ejemplo de esa página produce los resultados deseados:

 $ cat /tmp/data | histogram.py # NumSamples = 29; Max = 10.00; Min = 1.00 # Mean = 4.379310; Variance = 5.131986; SD = 2.265389 # each * represents a count of 1 1.0000 - 1.9000 [ 1]: * 1.9000 - 2.8000 [ 5]: ***** 2.8000 - 3.7000 [ 8]: ******** 3.7000 - 4.6000 [ 3]: *** 4.6000 - 5.5000 [ 4]: **** 5.5000 - 6.4000 [ 2]: ** 6.4000 - 7.3000 [ 3]: *** 7.3000 - 8.2000 [ 1]: * 8.2000 - 9.1000 [ 1]: * 9.1000 - 10.0000 [ 1]: * 

Media:

 awk '{sum += $1} END {print "mean = " sum/NR;}' filename 

Mediana:

 gawk -v max=128 ' function median(c,v, j) { asort(v,j); if (c % 2) return j[(c+1)/2]; else return (j[c/2+1]+j[c/2])/2.0; } { count++; values[count]=$1; if (count >= max) { print median(count,values); count=0; } } END { print "median = " median(count,values); }' filename 

Modo:

 awk '{c[$1]++;} END {for (i in count) {if (c[i]>max) {max=i;}} print "mode = " max;}' filename 

Este cálculo de modo requiere un número par de muestras, pero verá cómo funciona …

Desviación estándar:

 awk '{sum+=$1; sumsq+=$1*$1;} END {print "stdev = " sqrt(sumsq/NR - (sum/NR)**2);}' filename 

Por si acaso, hay datastat , un progtwig simple para Linux que computa estadísticas simples desde la línea de comandos. Por ejemplo,

 cat file.dat | datastat 

generará el valor promedio en todas las filas para cada columna de file.dat. Si necesita conocer la desviación estándar, mínima, máxima, puede agregar las --dev , --min y --max , respectivamente.

datastat tiene la posibilidad de agregar filas según el valor de una o más columnas “clave”. Por ejemplo,

 cat file.dat | datastat -k 1 

producirá, para cada valor diferente encontrado en la primera columna (la “clave”), el promedio de todos los demás valores de columna agregados entre todas las filas con el mismo valor en la clave. Puede usar más columnas como campos clave (p. Ej., -K 1-3, -k 2,4, etc.).

Está escrito en C ++, funciona rápido y con poca memoria ocupada, y se puede conectar con otras herramientas como cut , grep , sed , sort , awk , etc.

También podría considerar el uso de clistatos . Es una herramienta de interfaz de línea de comandos altamente configurable para calcular estadísticas para una secuencia de números de entrada delimitados.

Opciones de E / S

  • Los datos de entrada pueden ser de un archivo, entrada estándar o una tubería
  • La salida se puede escribir en un archivo, salida estándar o una tubería
  • La salida utiliza encabezados que comienzan con “#” para habilitar la conexión a la red

Opciones de análisis

  • Detección de señal, fin de archivo o línea en blanco para detener el procesamiento
  • Se pueden establecer caracteres de comentario y delimitador
  • Las columnas se pueden filtrar del procesamiento
  • Las filas se pueden filtrar del procesamiento en función de la restricción numérica
  • Las filas se pueden filtrar del procesamiento en función de la restricción de cadena
  • Las filas de encabezado iniciales se pueden omitir
  • Se puede procesar un número fijo de filas
  • Los delimitadores duplicados se pueden ignorar
  • Las filas se pueden volver a formar en columnas
  • Esforzar estrictamente que solo se procesen las filas del mismo tamaño
  • Una fila que contiene títulos de columna se puede usar para titular las estadísticas de salida

Opciones de estadísticas

  • Estadísticas de resumen (recuento, mínimo, promedio, máximo, desviación estándar)
  • Covarianza
  • Correlación
  • Mínimos cuadrados compensados
  • Pendiente de mínimos cuadrados
  • Histogtwig
  • Datos brutos después de filtrar

NOTA: soy el autor.

Me encontré con ganas de hacer esto en una tubería de shell, y obtener todos los argumentos correctos para R tomó un tiempo. Esto es lo que se me ocurrió:

seq 10 | R --slave -e 'x < - scan(file="stdin",quiet=TRUE); summary(x)' Min. 1st Qu. Median Mean 3rd Qu. Max. 1.00 3.25 5.50 5.50 7.75 10.00

La opción --slave "Make (s) R se ejecuta tan silenciosamente como sea posible ... Implica --quiet y --no-save". La opción -e le dice a R que trate la siguiente cadena como código R. La primera instrucción se lee de forma estándar en, y almacena lo que se lee en la variable llamada "x". La opción quiet=TRUE para la función de scan suprime la escritura de una línea que indica cuántos elementos se leyeron. La segunda statement aplica la función de summary a x , que produce la salida.

 #!/usr/bin/perl # # stdev - figure N, min, max, median, mode, mean, & std deviation # # pull out all the real numbers in the input # stream and run standard calculations on them. # they may be intermixed with other test, need # not be on the same or different lines, and # can be in scientific notion (avagadro=6.02e23). # they also admit a leading + or -. # # Tom Christiansen # tchrist@perl.com use strict; use warnings; use List::Util qw< min max >; # my $number_rx = qr{ # leading sign, positive or negative (?: [+-] ? ) # mantissa (?= [0123456789.] ) (?: # "N" or "N." or "NN" (?: (?: [0123456789] + ) (?: (?: [.] ) (?: [0123456789] * ) ) ? | # ".N", no leading digits (?: (?: [.] ) (?: [0123456789] + ) ) ) ) # abscissa (?: (?: [Ee] ) (?: (?: [+-] ? ) (?: [0123456789] + ) ) | ) }x; my $n = 0; my $sum = 0; my @values = (); my %seen = (); while (<>) { while (/($number_rx)/g) { $n++; my $num = 0 + $1; # 0+ is so numbers in alternate form count as same $sum += $num; push @values, $num; $seen{$num}++; } } die "no values" if $n == 0; my $mean = $sum / $n; my $sqsum = 0; for (@values) { $sqsum += ( $_ ** 2 ); } $sqsum /= $n; $sqsum -= ( $mean ** 2 ); my $stdev = sqrt($sqsum); my $max_seen_count = max values %seen; my @modes = grep { $seen{$_} == $max_seen_count } keys %seen; my $mode = @modes == 1 ? $modes[0] : "(" . join(", ", @modes) . ")"; $mode .= ' @ ' . $max_seen_count; my $median; my $mid = int @values/2; if (@values % 2) { $median = $values[ $mid ]; } else { $median = ($values[$mid-1] + $values[$mid])/2; } my $min = min @values; my $max = max @values; printf "n is %d, min is %g, max is %d\n", $n, $min, $max; printf "mode is %s, median is %g, mean is %g, stdev is %g\n", $mode, $median, $mean, $stdev; 

También hay simple-r, que puede hacer casi todo lo que R puede, pero con menos teclas presionadas:

https://code.google.com/p/simple-r/

Para calcular estadísticas descriptivas básicas, uno debería escribir una de:

 r summary file.txt r summary - < file.txt cat file.txt | r summary - 

Para cada una de las desviaciones promedio, mediana, mínima, máxima y estándar, el código sería:

 seq 1 100 | r mean - seq 1 100 | r median - seq 1 100 | r min - seq 1 100 | r max - seq 1 100 | r sd - 

No hay nada simple-R!

Otra herramienta más: https://www.gnu.org/software/datamash/

 # Example: calculate the sum and mean of values 1 to 10: $ seq 10 | datamash sum 1 mean 1 55 5.5 

Podría empaquetarse más comúnmente (la primera herramienta que encontré preempacada para nix al menos)

Usando xsv :

 $ echo '3 1 4 1 5 9 2 6 5 3 5 9' |tr ' ' '\n' > numbers-one-per-line.csv $ xsv stats -n < numbers-one-per-line.csv field,type,sum,min,max,min_length,max_length,mean,stddev 0,Integer,53,1,9,1,1,4.416666666666667,2.5644470922381863 # mode/median/cardinality not shown by default since it requires storing full file in memory: $ xsv stats -n --everything < numbers-one-per-line.csv | xsv table field type sum min max min_length max_length mean stddev median mode cardinality 0 Integer 53 1 9 1 1 4.416666666666667 2.5644470922381863 4.5 5 7 

Otra herramienta: tsv-summarize , de las utilidades tsv de eBay . Mínima, máxima, media, mediana, desviación estándar son compatibles. Destinado a grandes conjuntos de datos. Ejemplo:

 $ seq 10 | tsv-summarize --min 1 --max 1 --median 1 --stdev 1 1 10 5.5 3.0276503541 

Descargo de responsabilidad: soy el autor.