我有这样的数据:
1
2
3
4
5
我想对这列中的每N行求和(bin),但不喜欢:
awk '{s+=$1}NR%2==0{print s;s=0}' file
例如,对于2个分区,我想要对行1 + 2,2 + 3,3 + 4,4 + 5求和。所以它看起来像这样:
3
5
7
9
对于这样的3个binning:
6
9
12
有什么想法吗?
我的真实数据如下:
2014-04-13 17:25:33.25 5.5
2014-04-13 17:25:53.25 27.5
2014-04-13 17:26:13.26 -3.5
2014-04-13 17:26:33.26 5.5
2014-04-13 17:26:53.26 22.5
2014-04-13 17:27:12.27 1.5
2014-04-13 17:27:32.27 26.5
2014-04-13 17:27:52.27 -14.5
2014-04-13 17:28:12.28 26.5
2014-04-13 17:28:32.28 0.5
2014-04-13 17:28:52.28 -14.5
2014-04-13 17:29:12.29 12.5
2014-04-13 17:29:32.29 9.5
前两列是~20秒步的时间,3行是~1分钟。因此,例如,我想总结(bin)第3列,以获得在任何给定的30分钟(90行)或5分钟(15行)中总体变化的程度。
答案 0 :(得分:2)
像Awk中的这样
$ awk -v Bin=3 '{ tot += $3 } 0 == NR%Bin { print tot; tot = 0 }' data.txt
29.5
29.5
38.5
-1.5
但是你可能最好解析时间戳并使用awk的mktime()
来创建实际的时间段,而不是你的近似值。当然,除非你不需要那么高的精确度。
使用日期时间功能:
awk -v Bin=1 '
BEGIN { Step = Bin * 60; } # convert Bin in minutes to seconds
function Output () {
print strftime("%Y-%m-%d %T -", StartTime), strftime("%Y-%m-%d %T", EndTime), Total;
Total = 0;
StartTime += Step;
EndTime += Step;
}
{
Time = $1 OFS $2;
sub(/\.[0-9]+$/, "", Time);
gsub(/[-:.]/, OFS, Time);
Time = mktime(Time);
}
1 == NR {
StartTime = Time;
EndTime = StartTime + Step - 1;
}
Time > EndTime {
Output()
}
{
Total += $3;
}
END { Output() }
'
2014-04-13 17:25:33 - 2014-04-13 17:26:32 29.5
2014-04-13 17:26:33 - 2014-04-13 17:27:32 56
2014-04-13 17:27:33 - 2014-04-13 17:28:32 12.5
2014-04-13 17:28:33 - 2014-04-13 17:29:32 7.5
答案 1 :(得分:2)
您可以使用此功能,例如:
awk -v bin=THE_NUMBER-1 '{a[NR]=$1}
END {
for (i=1; i<=NR-bin; i++)
{
for (j=0; j<=bin; j++) {c+=a[i+j]}
print c; c=0
}
}' file
-v bin=THE_NUMBER-1
给出了价值。我们使用的是数字-1。{a[NR]=$1}
存储每行的值。END {}
在脚本结束时执行。{for (i=1; i<=NR-bin; i++)
循环显示行号,从第一行到最后一行减去bin
。{ for (j=0; j<=bin; j++) {c+=a[i+j]}
遍历受影响的行序列,并作出总和。{print c; c=0}
打印结果并重置计数器。对于您的给定示例文件1 2 3...
,它的工作方式如下:
$ awk -v bin=2 '{a[NR]=$1} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} print c; c=0}}' file
6
9
12
$ awk -v bin=1 '{a[NR]=$1} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} print c; c=0}}' file
3
5
7
9
如果您想将其他文件与日期一起使用,请将所有$1
替换为$NF
,以便将该文件的最后一列作为要检查的数字。
$ awk -v bin=1 '{a[NR]=$NF} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} printf "%.2f\n", c; c=0}}' a
33.00
24.00
2.00
28.00
24.00
28.00
12.00
12.00
27.00
-14.00
-2.00
22.00
$ awk -v bin=2 '{a[NR]=$NF} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} printf "%.2f\n", c; c=0}}' a
29.50
29.50
24.50
29.50
50.50
13.50
38.50
12.50
12.50
-1.50
7.50
$ awk -v bin=3 '{a[NR]=$NF} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} printf "%.2f\n", c; c=0}}' a
35.00
52.00
26.00
56.00
36.00
40.00
39.00
-2.00
25.00
8.00
$ awk -v bin=4 '{a[NR]=$NF} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} printf "%.2f\n", c; c=0}}' a
57.50
53.50
52.50
41.50
62.50
40.50
24.50
10.50
34.50
$ awk -v bin=5 '{a[NR]=$NF} END {for (i=1; i<=NR-bin; i++) { for (j=0; j<=bin; j++) {c+=a[i+j]} printf "%.2f\n", c; c=0}}' a
59.00
80.00
38.00
68.00
63.00
26.00
37.00
20.00