如何從第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支援數組,因此將數組用於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(字段數)。這樣即使最後一行的欄位為零,區塊中的輸出也能正常運作。minmaxEND

答案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>1NR>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

使用datamashprintf

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

相關內容