Awk
awk
可以對指定行數的列求和嗎
我已經查看了“類似問題”,但似乎沒有一個可以解決我的問題:
我有一個大的 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