como extrair valor máximo e mínimo da coluna 1 e coluna 2

como extrair valor máximo e mínimo da coluna 1 e coluna 2

Queridos, eu tenho umgrandearquivo de dados, digamosarquivo.dat, contém duas colunas

por exemplo, file.dat (mostrando algumas linhas)

    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 esperados

Quero encontrar/extrair o máximo e o mínimo de ambas as colunas, por exemplo, coluna-1

max - 0.4916
min - 0.0000

da mesma forma coluna-2

max - -23.4334
min - -24.1254

Solução incompleta (não funciona para a coluna 2)

Para Coluna-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 coluna-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

Por favor, ajude-me a encontrar o valor mínimo e máximo da coluna 2 nota: o arquivo de dados possui uma linha em branco no final do arquivo

Responder1

O problema no seu código,

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

... é que você imediatamente exitapós processar a primeira linha de entrada. Seu bloco do meio precisa ser acionado paratodolinha. Então, em um ENDbloco, você pode imprimir os valores encontrados. Você faz isso em outro trecho de código:

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

Outra questão é que você inicializa mincom um número mágico (9 no primeiro código que citei, e 0 na segunda parte; variáveis ​​que não são inicializadas explicitamente tem o valor 0 se você usá-las em cálculos). Se esse número mágico não estiver dentro do intervalo de números nos dados reais, os valores mínimo e/ou máximo calculados estarão errados. É melhor inicializar min e max com algum valor encontrado nos dados.

Para acompanharambosvalores mínimo e máximo, você precisa de duas variáveis, e ambas precisam ser verificadas nos dados do arquivo para cada linha, para ver se precisam de atualização.

Como awksuporta arrays, seria natural usar arrays para mine max, com um elemento de array por coluna. Isso é o que fiz no código abaixo.


Generalizado para qualquer número de colunas:

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 e os dados da pergunta:

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

A condição NF == 0para o primeiro bloco (que é executado para todas as linhas) é garantir que pulamos as linhas em branco. O teste significa "se houver zero campos (colunas) de dados nesta linha". A variável initializedserá zero desde o início (logicamentefalso), mas será definido como um (logicamenteverdadeiro) assim que a primeira linha que contém dados for lida.

A nfvariável é inicializada para NF(o número de campos) na linha a partir da qual inicializamos os valores mine max. Isso ocorre para que a saída do ENDbloco funcione mesmo que a última linha tenha zero campos.

Responder2

Na verdade, você pode combinar todas as instruções em um 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

Isso inicializará os valores mínimo e máximo de ambas as colunas com os respectivos valores da primeira linha (regra com condição NR==1) e, em seguida, verificará as linhas sucessivas para ver se os valores são maiores que o máximo atual/menores que o mínimo atual, respectivamente (regra com condição NR>1).

No final do arquivo (regra com condição END), imprime o resultado.

Perceberque isso pressupõenão há linhas vazias. Se houver, você deverá substituir a NR>1condição por NR>1 && NF>0. Se pode haver linhas vaziasantes do primeiro, 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

Isso usará uma variável initpara verificar se uma linha não vazia já foi encontrada e usará o conteúdo da primeira linha não vazia para pré-definir o máximo/mínimo atual para ambas as colunas. Somente se initestiver definido (após esta inicialização) as linhas (não vazias) serão consideradas para inserir essa estatística.

Como observação geral, você nunca precisa criar catum arquivo e canalizar o resultado para awk.

Responder3

Usandodatamashe 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

...ou sem loop:

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)

Saída de:

Column #1
max - 0.4916
min - 0

Column #2
max - -23.4334
min - -24.1254

Responder4

Isto para a coluna 1 (calcula a média máxima e mínima)

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

isso para a coluna 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}'

informação relacionada