Shell 在所有列中使用awk的移动平均值
我的数据如下:Shell 在所有列中使用awk的移动平均值,shell,awk,moving-average,Shell,Awk,Moving Average,我的数据如下: 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个过去的数字的移动平均值 期望输出为: 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 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个过去的数字的移动平均值
期望输出为:
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
您可以使用三条规则来实现这一点,即对存储在两个数组a[]和b[]中的值使用滑动窗口。您只需使用计数器n作为索引填充每个元素,然后当n>=5时,输出总和并删除a[n-4]和b[n-4]处的值(可选),然后继续。你的第一条规则是,加上一个循环和每个循环中最后5个值的总和,得到平均值 第二条规则只是验证您有2个字段,并填充a[]和b[]数组。您可以添加测试以确保field1和field2都是数值,这由您自己决定 第三个规则是计算并输出最终总和的结束规则,例如
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
保持流动资金
如果您确实希望继续运行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
输出是相同的。您可以使用三条规则来完成这项工作,即使用滑动窗口来显示存储在两个数组a[]和b[]中的值。您只需使用计数器n作为索引填充每个元素,然后当n>=5时,输出总和并删除a[n-4]和b[n-4]处的值(可选),然后继续。你的第一条规则是,加上一个循环和每个循环中最后5个值的总和,得到平均值 第二条规则只是验证您有2个字段,并填充a[]和b[]数组。您可以添加测试以确保field1和field2都是数值,这由您自己决定 第三个规则是计算并输出最终总和的结束规则,例如
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
保持流动资金
如果您确实希望继续运行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
输出相同。这里是另一个awk,使用2次通过:
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通道的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
请您尝试下面的方法,再添加一种方法。使用GNU awk中显示的样本编写和测试
请您尝试下面的方法,再添加一种方法。使用GNU awk中显示的样本编写和测试
当将整个系统加载到内存中时,所有呈现的结果都非常占用内存。虽然有些人会删除分配的内存,但只使用模块化索引更容易。最重要的是,你不需要经常用浮点数重新计算和,如果你有高精度的要求,我会提出不同的观点,但对于整数,它是不需要的: 此解决方案假定列数相等,滑动窗口为n:
当将整个系统加载到内存中时,所有呈现的结果都非常占用内存。虽然有些人会删除分配的内存,但只使用模块化索引更容易。最重要的是,你不需要经常用浮点数重新计算和,如果你有高精度的要求,我会提出不同的观点,但对于整数,它是不需要的: 此解决方案假定列数相等,滑动窗口为n:
++相信这一个更有效,有趣的是,你的第一个想法并不总是最有效的,但当你开始修补时,你会发现一路上有改进。。。除非您的Ed或Charles:@Kay,否则我回滚了编辑,因为使用shell变量的$n1的使用应该使用-v选项或BEGIN规则来处理,以使其成为awk变量。否则,美元的报价和逃逸将变得脆弱。我喜欢你做的概括和清理的格式虽然!对非常感谢。我的意思是delete-gladunset是无害的,它一定曾经被使用过,或者是某物的同义词。接得好!++相信这一个更有效,有趣的是,你的第一个想法并不总是最有效的,但当你开始修补时,你会发现一路上有改进。。。除非您的Ed或Charles:@Kay,否则我回滚了编辑,因为使用shell变量的$n1的使用应该使用-v选项或BEGIN规则来处理,以使其成为awk变量。否则,美元的报价和逃逸将变得脆弱。我喜欢你做的概括和清理的格式虽然!对非常感谢。我的意思是delete-gladunset是无害的,它一定曾经被使用过,或者是某物的同义词。抢手货好的,我明白了,你对输入进行了两次传递。我必须记住这一点。我已经看过好几次了,这真的很好。好吧,我明白了,你对输入进行了两次传递。我必须记住这一点。我已经看过好几次了,真是太棒了,太棒了!!好极了!!
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