열 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... 첫 번째 입력 줄을 처리한 직후 입니다 . 중간 블록이 트리거되어야 합니다.모든선. 그런 다음 END찾은 값을 블록에서 인쇄할 수 있습니다. 다른 코드 조각에서 이 작업을 수행합니다.

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

또 다른 문제는 min매직 넘버(인용한 첫 번째 코드에서는 9, 두 번째 부분에서는 0, 명시적으로 초기화되지 않은 변수는 계산에 사용하는 경우 값이 0임)로 초기화한다는 것입니다. 이 매직 넘버가 실제 데이터의 숫자 범위에 속하지 않으면 계산된 최소값 및/또는 최대값이 잘못됩니다. min과 max를 모두 데이터에서 발견된 값으로 초기화하는 것이 좋습니다.

추적하려면둘 다최소 및 최대 값을 사용하려면 두 개의 변수가 필요하며, 이 두 변수는 업데이트가 필요한지 확인하기 위해 모든 줄에 대해 파일의 데이터와 비교하여 확인해야 합니다.

배열을 지원 하므로 및 열당 배열 요소가 하나씩 있는 awk배열을 사용하는 것이 자연스럽습니다 . 이것이 제가 아래 코드에서 수행한 작업입니다.minmax


임의 개수의 열로 일반화됨:

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은 빈 라인을 건너뛰는 것입니다. 테스트는 "이 줄에 데이터 필드(열)가 0개인 경우"를 의미합니다. 변수는 initialized처음부터 0이 됩니다(논리적으로거짓)이지만 1로 설정됩니다(논리적으로는진실) 데이터가 있는 첫 번째 줄을 읽자마자.

변수 는 및 값을 초기화하는 줄의 (필드 수) nf로 초기화됩니다 . 이는 마지막 줄에 필드가 0인 경우에도 블록 의 출력이 작동하도록 하기 위한 것입니다 .NFminmaxEND

답변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}'

이것은 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}'

관련 정보