как извлечь максимальное и минимальное значение из столбца 1 и столбца 2

как извлечь максимальное и минимальное значение из столбца 1 и столбца 2

Дорогие все, у меня естьбольшойфайл данных, скажем,файл.dat, он содержит два столбца

например, file.dat (показывает несколько строк)

    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

Ожидаемые результаты

Я хочу найти/извлечь максимум и минимум из обоих столбцов, например, столбец-1

max - 0.4916
min - 0.0000

аналогично столбец-2

max - -23.4334
min - -24.1254

Неполное решение (не работает для столбца 2)

Для столбца-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

для столбца-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**

Проблема

Пожалуйста, помогите мне найти минимальное и максимальное значение из столбца 2. примечание: файл данных имеет пустую строку в конце файла

решение1

Проблема в вашем коде,

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

... это то, что вы сразу exitпосле обработки первой строки ввода. Ваш средний блок там должен быть запущен длякаждыйline. Затем в ENDблоке вы можете вывести найденные вами значения. Это делается в другом фрагменте кода:

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

Другая проблема заключается в том, что вы инициализируете minс помощью магического числа (9 в первом коде, который я процитировал, и 0 во втором фрагменте; переменные, которые явно не инициализируются, имеют значение 0, если вы используете их в вычислениях). Если это магическое число не попадает в диапазон чисел в реальных данных, то вычисленные значения min и/или max будут неверными. Лучше инициализировать и min, и max каким-то значением, найденным в данных.

Следить заобаДля значений min и max вам понадобятся две переменные, и обе из них необходимо проверить по данным в файле для каждой строки, чтобы увидеть, нуждаются ли они в обновлении.

Поскольку awkподдерживает массивы, было бы естественно использовать массивы для minи max, с одним элементом массива на столбец. Это то, что я сделал в коде ниже.


Обобщенно для любого количества столбцов:

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])
}

Учитывая этот сценарий и данные в вопросе:

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

Условие NF == 0для первого блока (который выполняется для всех строк) — гарантировать, что мы пропускаем пустые строки. Тест означает «если в этой строке нет нулевых полей (столбцов) данных». Переменная initializedбудет равна нулю с самого начала (логическиЛОЖЬ), но будет установлен на единицу (логическиистинный) как только будет прочитана первая строка, содержащая данные.

Переменная nfинициализируется NF(количеством полей) на строке, из которой мы инициализируем значения minи max. Это делается для того, чтобы вывод в ENDблоке работал, даже если последняя строка имеет нулевые поля.

решение2

На самом деле, вы можете объединить все инструкции в одну awkпрограмму:

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

Это позволит инициализировать минимальные и максимальные значения для обоих столбцов с соответствующими значениями первой строки (правило с условием NR==1), а затем просканировать последующие строки, чтобы увидеть, являются ли значения больше текущего максимума/меньше текущего минимума соответственно (правило с условием NR>1).

В конце файла (правило с условием END) выводится результат.

Уведомлениечто это предполагаетнет пустых строк. Если есть, то нужно заменить NR>1условие наNR>1 && NF>0 . Если могут быть пустые строкиперед первым, использовать

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

Это будет использовать переменную initдля проверки того, была ли уже найдена непустая строка, и использовать содержимое первой непустой строки для предварительной установки текущего максимума/минимума для обоих столбцов. Только если initустановлено (после этой инициализации), (непустые) строки рассматриваются для ввода этой статистики.

В качестве общего замечания, вам никогда не придется сохранять catфайл и передавать результат в awk.

решение3

С использованиемdatamashи 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

...или без цикла:

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)

Вывод либо:

Column #1
max - 0.4916
min - 0

Column #2
max - -23.4334
min - -24.1254

решение4

Это для столбца 1 (он вычисляет среднее максимальное и минимальное значение)

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

это для col 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}'

Связанный контент