cómo extraer el valor máximo y mínimo de la columna 1 y la columna 2

cómo extraer el valor máximo y mínimo de la columna 1 y la columna 2

Queridos todos, tengo ungrandearchivo de datos digamosarchivo.dat, contiene dos columnas

por ejemplo, file.dat (mostrando algunas filas)

    0.0000  -23.4334
    0.0289  -23.4760
    0.0578  -23.5187
    0.0867  -23.5616
    0.1157  -23.6045
    0.1446  -23.6473
    0.1735  -23.6900
    0.2024  -23.7324
    0.2313  -23.7745
    0.2602  -23.8162
    0.2892  -23.8574
    0.3181  -23.8980
    0.3470  -23.9379
    0.3759  -23.9772
    0.4048  -24.0156
    0.4337  -24.0532
    0.4627  -24.0898
    0.4916  -24.1254
note: data file has a blank line at the end of the file

Resultados previstos

Quiero encontrar/extraer el máximo y el mínimo de ambas columnas, por ejemplo, columna-1

max - 0.4916
min - 0.0000

de manera similar columna-2

max - -23.4334
min - -24.1254

Solución incompleta (no funciona para la columna 2)

Para la columna 1

awk 'BEGIN{min=9}{for(i=1;i<=1;i++){min=(min<$i)?min:$i}print min;exit}' file.dat 
0.0000
cat file.dat | awk '{if ($1 > max) max=$1}END{print max}'
0.4916

para la columna-2

awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat
-23.4334

cat file.dat | awk '{if ($2 > max) max=$2}END{print max}'
**no output showing**

Problema

Ayúdenme a encontrar el valor mínimo y máximo de la columna 2 nota: el archivo de datos tiene una línea en blanco al final del archivo

Respuesta1

El problema en su código,

awk 'BEGIN{min=9}{for(i=2;i<=2;i++){min=(min<$i)?min:$i}print min;exit}' file.dat

... es que usted inmediatamente exitdespués de procesar la primera línea de entrada. Tu bloque central debe activarse paracadalínea. Luego, en un ENDbloque, puedes imprimir los valores que has encontrado. Haz esto en otro fragmento de código:

awk '{if ($1 > max) max=$1}END{print max}'

Otro problema es que inicializas mincon un número mágico (9 en el primer código que cité y 0 en la segunda parte; las variables que no se inicializan explícitamente tienen el valor 0 si las usas en los cálculos). Si este número mágico no se encuentra dentro del rango de números en los datos reales, entonces los valores mínimos y/o máximos calculados serán incorrectos. Es mejor inicializar tanto el mínimo como el máximo con algún valor encontrado en los datos.

Seguirle el rastro aambosvalores mínimo y máximo, necesita dos variables, y ambas deben compararse con los datos del archivo para cada línea, para ver si es necesario actualizarlas.

Como awkadmite matrices, sería natural utilizar matrices para miny max, con un elemento de matriz por columna. Esto es lo que he hecho en el código siguiente.


Generalizado a cualquier número de columnas:

NF == 0 {
        # Skip any line that does not have data
        next
}

!initialized {
        # Initialize the max and min for each column from the
        # data on the first line of input that has data.
        # Then immediately skip to next line.

        nf = NF

        for (i = 1; i <= nf; ++i)
                max[i] = min[i] = $i

        initialized = 1
        next
}

{
        # Loop over the columns to see if the max and/or min
        # values need updating.

        for (i = 1; i <= nf; ++i) {
                if (max[i] < $i) max[i] = $i
                if (min[i] > $i) min[i] = $i
        }
}

END {
        # Output max and min values for each column.

        for (i = 1; i <= nf; ++i)
                printf("Column %d: min=%s, max=%s\n", i, min[i], max[i])
}

Dado este script y los datos de la pregunta:

$ awk -f script.awk file
Column 1: min=0.0000, max=0.4916
Column 2: min=-24.1254, max=-23.4334

La condición NF == 0para el primer bloque (que se ejecuta para todas las líneas) es garantizar que omitimos las líneas en blanco. La prueba significa "si hay cero campos (columnas) de datos en esta línea". La variable initializedserá cero desde el principio (lógicamenteFALSO), pero se establecerá en uno (lógicamenteverdadero) tan pronto como se lee la primera línea que tiene datos.

La nfvariable se inicializa en NF(el número de campos) en la línea desde la que inicializamos los valores miny max. Esto es para que la salida del ENDbloque funcione incluso si la última línea tiene cero campos.

Respuesta2

En realidad, puedes combinar todas las instrucciones en un solo awkprograma:

awk 'NR==1{min1=max1=$1;min2=max2=$2}\
     NR>1 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
            if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
     END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat

Esto inicializará los valores mínimo y máximo para ambas columnas con los valores respectivos de la primera fila (regla con condición NR==1) y luego escaneará las filas sucesivas para ver si los valores son mayores que el máximo actual/menores que el mínimo actual, respectivamente. (regla con condición NR>1).

Al final del archivo (regla con condición END), imprime el resultado.

Avisoque esto suponeno hay líneas vacías. Si es así, debe reemplazar la NR>1condición con NR>1 && NF>0. Si puede haber líneas vacíasantes del primero, usar

awk '!init && NF>0 {init=1; min1=max1=$1; min2=max2=$2} \
     init==1 && NF>0 {if ($1<min1) {min1=$1} else if ($1>max1) {max1=$1};\
                      if ($2<min2) {min2=$2} else if ($2>max2) {max2=$2}; }\
     END{printf("Column1 min: %f\nColumn1 max: %f\nColumn2 min: %f\nColumn2 max:%f\n",min1,max1,min2,max2)}' file.dat

Esto utilizará una variable initpara comprobar si ya se encontró una línea no vacía y utilizará el contenido de la primera línea no vacía para preestablecer el máximo/mínimo actual para ambas columnas. Solo si initse establece (después de esta inicialización) se consideran las líneas (no vacías) para ingresar esa estadística.

Como observación general, nunca es necesario crear catun archivo y canalizar el resultado a awk.

Respuesta3

Usandodatamashy printf:

for f in 1 2 ; do  printf 'Column #%s\nmax - %s\nmin - %s\n\n' $f \
                   $(datamash -W max $f min $f < file.dat); done

...o sin bucle:

printf 'Column #%s\nmax - %s\nmin - %s\n\n' \
       $(datamash -W max 1 min 1 max 2 min 2 < file.dat | 
         tr -s '\t' '\n' | paste - - | nl)

Salida de cualquiera de los dos:

Column #1
max - 0.4916
min - 0

Column #2
max - -23.4334
min - -24.1254

Respuesta4

Esto para la columna 1 (calcula el promedio máximo y mínimo)

sort -n -k 1 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1}  END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'

esto para la columna 2

sort -n -k 2 file |awk '{SUM+=$1 ; if ( NR == 1) MIN=$1}  END{print "Average - "SUM/NR, "Min time - "MIN,"Max Time - "$1}'

información relacionada