[英]Moving average using awk in all columns
我有一个数据:
2 2
3 3
4 3
2 2
1 1
56 4
3 2
4 1
2 2
4 2
5 5
3 3
5 6
6 4
我想打印所有列的每 5 个过去数字的移动平均线。
愿望 Output 是:
2.4 2.2
13.2 2.6
13.2 2.4
13.2 2
13.2 2
13.8 2.2
3.6 2.4
3.6 2.6
3.8 3.6
4.6 4
您可以通过三个规则使用“滑动窗口”来存储两个 arrays a[]
和b[]
中的值。 您只需使用计数器n
作为索引填充每个元素,然后当n >= 5
output 求和并delete
a[n-4]
和b[n-4]
处的值(可选)并继续。 您的第一条规则就是这样(添加一个循环和每个平均值的最后 5 个值的总和。
您的第二条规则只是验证您有 2 个字段并填写a[]
和b[]
arrays。 (您可以添加测试以确保 field1 和 field2 都是数值——这留给您)
您的第三条规则是计算并输出最终总和的END
规则,例如
awk '
n >= 5 {
suma=sumb=0
for (i = n-4; i <= n; i++) {
suma+=a[i]
sumb+=b[i]
}
print suma/5"\t"sumb/5
delete a[n-4]
delete b[n-4]
}
NF >= 2 {
a[++n] = $1
b[n] = $2
}
END {
suma=sumb=0
for (i = n-4; i <= n; i++) {
suma+=a[i]
sumb+=b[i]
}
print suma/5"\t"sumb/5
}
' data
(而不是循环计算总和,您可以继续运行总和并从 arrays 中减去您未unset
的值——由您决定)
示例使用/输出
您可以简单地使用 xterm 并切换到存储data
文件的目录(根据需要更改名称),然后选择复制上面的awk
脚本并用鼠标中键粘贴到 xterm。 您将收到:
2.4 2.2
13.2 2.6
13.2 2.4
13.2 2
13.2 2
13.8 2.2
3.6 2.4
3.6 2.6
3.8 3.6
4.6 4
保持运行总和
如果您确实想继续运行总和( suma
和sumb
)并删除n-4
处的值而不是循环(这会更有效),您可以这样做:
awk '
n >= 5 {
print suma/5"\t"sumb/5
suma -= a[n-4]
sumb -= b[n-4]
}
NF >= 2 {
a[++n] = $1
b[n] = $2
suma += a[n]
sumb += b[n]
}
END {
print suma/5"\t"sumb/5
}
' data
output 是一样的。
这是另一个使用 2 遍的awk
:
awk -v OFS='\t' 'FNR == NR {
a[FNR] = $1
b[FNR] = $2
for (i=FNR-4; FNR>= 5 && i<=FNR; i++) {
sum1[FNR-4] += a[i]
sum2[FNR-4] += b[i]
}
tr = FNR
next
}
FNR <= tr-4 {
printf "%.2f%s%.2f\n", sum1[FNR]/5, OFS, sum2[FNR]/5
}' file file
2.40 2.20
13.20 2.60
13.20 2.40
13.20 2.00
13.20 2.00
13.80 2.20
3.60 2.40
3.60 2.60
3.80 3.60
4.60 4.00
您能否尝试以下操作,添加另一种方法。 使用 GNU awk
中的示例编写和测试。
awk '
FNR==NR{
a[FNR]=$1
b[FNR]=$2
lines++
next
}
FNR<=(lines-4){
++count
for(i=count;i<=(4+count);i++){
sum1+=a[i]
sum2+=b[i]
}
print sum1/5,sum2/5
sum1=sum2=""
}
' Input_file Input_file | column -t
所有呈现的结果都是非常密集的 memory,因为将整个系统加载到 memory 中。 虽然有些删除分配的 memory,但使用模块化索引更容易。 最重要的是,您实际上并不需要不断地重新计算总和(如果您有高精度需求,我会以不同的方式争论浮点数,但对于整数则不需要):
此解决方案假定列数相等且滑动 window 为n
:
awk -v n=5 '{for(i=1;i<=NF;++i) {s[i] = s[i] - a[FNR%n,i] + $i; a[FNR%n,i]=$i } }
(FNR >= n) { for(i=1;i<=NF;++i) printf "%s" (i==NF?ORS:OFS), s[i]/n }' file
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.