Awk

awk 可以對指定行數的列求和嗎

  • January 7, 2021

我已經查看了“類似問題”,但似乎沒有一個可以解決我的問題:

我有一個大的 CSV 輸入文件;文件中的每一行都是一個x,y數據點。這裡有幾行用於說明,但請注意,通常數據不是 單調的:

1.904E-10,2.1501E+00  
3.904E-10,2.1827E+00  
5.904E-10,2.1106E+00  
7.904E-10,2.2311E+00  
9.904E-10,2.2569E+00  
1.1904E-09,2.3006E+00  

我需要創建一個小於輸入文件的輸出文件。對於輸入文件中的每N 行,輸出文件將包含不超過 一行。輸出文件中的每一行都是一個數據點,它是輸入文件N 行值的平均值。x,y``x,y

例如,如果輸入文件中的總行數為 3,000,並且N=3,則輸出文件將包含不超過1,000 行。使用上面的數據來完成這個例子,上面的前 3 行數據將被替換為一行,如下所示:

x = (1.904E-10 + 3.904E-10 + 5.904E-10) / 3 = 3.904E-10

y = (2.1501E+00 + 2.1827E+00 + 2.1106E+00) / 3 = 2.1478E+00,或:

3.904E-10,2.1478E+00 

對於輸出文件的一行。

我已經擺弄了一段時間,但還沒有做對。這是我一直在使用的,但我看不到如何迭代NR值以處理整個文件:

awk -F ',' 'NR == 1, NR == 3 {sumx += $1; avgx = sumx / 3; sumy += $2; avgy = sumy / 3} END {print avgx, avgy}' CB07-Small.csv

為了使這更複雜一點,我需要進一步“精簡”我的輸出文件:

如果avgy(如上計算)的值接近輸出文件中的最後一個值avgy,我不會將其作為新數據點添加到輸出文件中。相反,我將從輸入文件的下N 行avgx計算下一個&avgy值。***“關閉”***應定義為最後一個值的百分比。例如:argy

如果目前計算的值與輸出文件中記錄avgy的最後一個值的差異小於 10% avgy,則不要將新值寫入輸出文件。

查看編輯歷史

這是一個通用變體:

BEGIN { OFS = FS = "," }

{
   for (i = 1; i <= NF; i++) sum[i] += $i
   count++
}

count % 3 == 0 {
   for (i = 1; i <= NF; i++) $i = sum[i] / count
   delete sum
   count = 0
   if ($NF >= 1.1 * last || $NF <= 0.9 * last) {
       print
       last = $NF
   }
}


END {
   if (count > 0) {
       for (i = 1; i <= NF; i++) $i = sum[i] / count
       if ($NF >= 1.1 * last || $NF <= 0.9 * last) print
   }
}

我假設應該以與N行塊類似的方式處理剩餘部分。

這將檢查線路條件和 10% 規則。請記住,10% 規則具有線性增加檢查值的副作用。

$ awk -F ',' '
 BEGIN{
   N=3; prev_y=0
 }
 {
   x+=$1;
   y+=$2;
   i++
 }
 NR%N==0 && (y/i) <= (prev_y)*1.1{ x=0; y=0; i=0 }
 NR%N==0 && (y/i) > (prev_y)*1.1{
   print x/i","y/i;
   prev_y=y/i; x=0; y=0; i=0
 }' file

引用自:https://unix.stackexchange.com/questions/627800