Tengo una lista de números en un archivo, uno por línea. ¿Cómo puedo obtener los valores mínimo, máximo, mediano y promedio ? Quiero usar los resultados en un script bash.
Aunque mi situación inmediata es para enteros, una solución para números de punto flotante sería útil en el futuro, pero un método entero simple está bien.
bash
awk
arithmetic
bc
Peter.O
fuente
fuente
Respuestas:
Puede utilizar el lenguaje de programación R .
Aquí hay un script R rápido y sucio:
Tenga
"stdin"
en cuentascan
que hay un nombre de archivo especial para leer desde la entrada estándar (es decir, desde tuberías o redirecciones).Ahora puede redirigir sus datos sobre stdin al script R:
También funciona para puntos flotantes:
Si no desea escribir un archivo de secuencia de comandos R, puede invocar una línea única verdadera (con salto de línea solo para facilitar la lectura) en la línea de comando usando
Rscript
:Lea los excelentes manuales de R en http://cran.r-project.org/manuals.html .
Lamentablemente, la referencia completa solo está disponible en PDF. Otra forma de leer la referencia es escribiendo
?topicname
el aviso de una sesión interactiva de R.Para completar: hay un comando R que genera todos los valores que desea y más. Desafortunadamente, en un formato amigable para los humanos que es difícil de analizar mediante programación.
fuente
r-base
.R
el lenguaje es claramente el mejor para mi requerimiento en esta situación. Según la respuesta de Gilles, laRscript
interfaz para los archivos de script es la más apropiada (vs.R
, que es la interfaz interactiva) ... y R en la terminal es una calculadora útil , o entorno de prueba (como python :)cat datafile | Rscript -e 'print(summary(scan("stdin")));'
De hecho, mantengo un pequeño programa awk para dar la suma, el recuento de datos, el dato mínimo, el dato máximo, la media y la mediana de una sola columna de datos numéricos (incluidos los números negativos):
El script anterior lee de stdin e imprime columnas de salida separadas por tabuladores en una sola línea.
fuente
NR==1
puede irse (un uso inútil de- si) junto con las comprobaciones mín. / máx., por lo que todas las inicializaciones se pueden ubicar en la sección COMENZAR (¡bueno!) ... Permitir comentarios también es un buen toque ... Gracias, +1 ...awk
asumirá que las variables "nuevas" son cero, por lo que en este caso laBEGIN{}
sección es innecesaria. He arreglado el ajuste (tampoco es necesario escapar de los saltos de línea). También solíaOFS="\t"
limpiar laprint
línea e implementé el segundo comentario de @ Peter.O. (Sí, mi expresión regular lo permite.
, pero como loawk
interpreta0
, eso es aceptable.)awk
guión ahora es sustancialmente diferente. Casi siento que debería tomar crédito por el programa anterior, a fin de dar crédito donde se debe.Con GNU datamash :
fuente
brew install datamash
le ofrece una versión funcional para macOS, si tiene instalado Hombrew.Mínimo, máximo y promedio son bastante fáciles de obtener con awk:
Calcular la mediana es un poco más complicado, ya que necesita ordenar los números y almacenarlos en la memoria por un tiempo o leerlos dos veces (la primera vez para contarlos, la segunda, para obtener el valor de la mediana). Aquí hay un ejemplo que almacena todos los números en la memoria:
fuente
asort
lugar de la tubería.sort
, y parece ordenar correctamente los enteros y decimales. Aquí hay un enlace a mi versión resultante paste.ubuntu.com/612674 ... (Y una nota para Kim: He estado experimentando con awk durante un par de horas) Trabajar con un ejemplo de interés personal es mucho mejor para mí) ... Una nota general para los lectores: todavía estoy interesado en ver otros métodos. cuanto más compacto, mejor. Esperaré un momento ...Pythonpy funciona bien para este tipo de cosas:
fuente
Mínimo:
Máximo:
Mediana:
Promedio:
En
jq
la opción-s
(--slurp
) crea una matriz para las líneas de entrada después de analizar cada línea como JSON, o como un número en este caso.fuente
fuente
echo file.txt
tal vez no parece del todo correctocat
Y un revestimiento Perl one- (largo), que incluye la mediana:
Las opciones especiales utilizadas son:
-0777
: lea todo el archivo a la vez en lugar de línea por línea-a
: autosplit en la matriz @FUna versión de script más legible de lo mismo sería:
Si desea decimales, reemplácelos
%d
con algo como%.2f
.fuente
Simple-r es la respuesta:
Utiliza el entorno R para simplificar el análisis estadístico.
fuente
Solo por el hecho de tener una variedad de opciones presentadas en esta página, aquí hay dos formas más:
1: octava
Aquí hay un ejemplo rápido de octava.
2: bash + herramientas de un solo propósito .
Para que bash maneje números de punto flotante, este script usa
numprocess
ynumaverage
desde el paquetenum-utils
.PD. También he tenido una visión razonable
bc
, pero para este trabajo en particular, no ofrece nada más allá de lo queawk
ofrece. Es (como dice la 'c' en 'bc') una calculadora, una calculadora que requiere mucha programaciónawk
y este script bash ...fuente
Voy a la segunda opción de Lesmana de R y ofrecer mi primer programa de I. Lee un número por línea en la entrada estándar y escribe cuatro números (mínimo, máximo, promedio, mediano) separados por espacios en la salida estándar.
fuente
R
es la interfaz interactiva, yRscript
maneja los archivos con secuencias de comandos, que pueden ser ejecutables según su ejemplo hash-bang , o invocado desde un script bash. Los scripts pueden manejar argumentos de línea de comandos (por ejemplo, stackoverflow.com/questions/2045706/… ) para que se vea bien ... También se pueden usar expresiones R en bash a través de-e
... pero me pregunto cómoR
se compara conbc
...El siguiente
sort
/awk
tándem lo hace:(calcula la mediana como media de los dos valores centrales si el recuento de valores es par)
fuente
Tomando señales del código de Bruce, aquí hay una implementación más eficiente que no mantiene todos los datos en la memoria. Como se indicó en la pregunta, se supone que el archivo de entrada tiene (como máximo) un número por línea. Cuenta las líneas en el archivo de entrada que contienen un número calificado y pasa la cuenta al
awk
comando junto con (antes) los datos ordenados. Entonces, por ejemplo, si el archivo contieneentonces la entrada a
awk
es en realidadLuego, el
awk
script captura el recuento de datos en elNR==1
bloque de código y guarda el valor medio (o los dos valores medios, que se promedian para obtener la mediana) cuando los ve.fuente
cat
comandos innecesarios ; ver UUOC . ... (Continúa)FILENAME
y sabe a qué lo configura, pero, en general, siempre debe citar las variables de shell a menos que tenga una buena razón para no hacerlo, y Seguro que sabes lo que estás haciendo. (4) Tanto su respuesta como la de Bruce ignoran la entrada negativa (es decir, los números que comienzan con-
); No hay nada en la pregunta que sugiera que este sea el comportamiento correcto o deseado. No te sientas mal; Han pasado más de cuatro años y, aparentemente, soy la primera persona que se da cuenta.cat
y agregué la explicación.El
num
es un pequeñoawk
contenedor que hace exactamente esto y más, por ejemplole evita reinventar la rueda en el awk ultraportátil. Los documentos se proporcionan arriba y el enlace directo aquí (consulte también la página de GitHub ).
fuente
Con
perl
:fuente
cat/python
única solución: ¡ no es una prueba de entrada vacía!fuente
Si está más interesado en la utilidad en lugar de ser genial o inteligente, entonces
perl
es una opción más fácil queawk
. En general, estará en cada * nix con un comportamiento constante, y es fácil y gratuito de instalar en Windows. Creo que también es menos críptico queawk
eso, y habrá algunos módulos de estadísticas que podrías usar si quisieras un punto intermedio entre escribirlo tú mismo y algo como R. Mi bastante no probado (de hecho, sé que tiene errores pero funciona para mis propósitos ) elperl
guión tardó aproximadamente un minuto en escribirse, y supongo que la única parte críptica seríawhile(<>)
, que es la taquigrafía muy útil, lo que significa tomar los archivos pasados como argumentos de línea de comandos, leer una línea a la vez y poner esa línea en la variable especial$_
. Entonces podría poner esto en un archivo llamado count.pl y ejecutarlo comoperl count.pl myfile
. Aparte de eso, debería ser dolorosamente obvio lo que está sucediendo.fuente
fuente
sh
) como intérprete. También hay un problema con la forma en que los datos se leen en la matriz desde el archivo.