我有一个非常大的CSV文件,其内容如下:
# col1 col2 col3
1 1 7 9
2 2 8 10
3 3 9 11
4 4 10 12
5 5 11 13
6 6 12 14
对于所有列,我想计算每个连续两个字段的平均值,然后偏移到接下来的两个字段。例如,col1
平均值1
和2
是结果列的第一个单元格,3
和{{1}的平均值}}是结果列的第二个单元格。因此,新列大小原来4
的一半。
对于上面提供的示例文件,脚本的输出应如下所示:
col1
这个问题似乎是一个很好的[一]用AWK解决,但我仍然是使用AWK的新手。
任何指针都表示赞赏。
答案 0 :(得分:2)
可以使用awk
完成。
awk 'BEGIN { OFS = "\t" }
NR ==1 { print; next } # Print header
NR%2==0 { for (i = 2; i <= NF; i++) old[i] = $i; }
NR%2==1 { for (i = 2; i <= NF; i++) $i = ($i + old[i])/2
$1 = (NR-1)/2; print }'
old
数组中的末尾。示例输出:
# col1 col2 col3
1 1.5 7.5 9.5
2 3.5 9.5 11.5
3 5.5 11.5 13.5
此脚本接受一个参数,该参数是要组合在一起的行数,如果未指定参数,则默认为2。如评论中所述,代码需要将old
数组值重置为0,并对值求和而不是赋值。
$ cat x.awk
awk -v N=${1:-2} \
'BEGIN { OFS = "\t" }
NR ==1 { print; next } # Print header
NR%N!=1 { for (i = 2; i <= NF; i++) old[i] += $i }
NR%N==1 { for (i = 2; i <= NF; i++) $i = ($i + old[i])/N
$1 = int((NR-1)/N)
print
for (i = 2; i <= NF; i++) old[i] = 0
}' data
$ cat data
# col1 col2 col3
1 1 7 9
2 2 8 10
3 3 9 11
4 4 10 12
5 5 11 13
6 6 12 14
7 7 14 17
8 8 16 19
9 9 18 22
10 10 20 26
11 11 22 28
12 12 24 29
$ bash x.awk 2
# col1 col2 col3
1 1.5 7.5 9.5
2 3.5 9.5 11.5
3 5.5 11.5 13.5
4 7.5 15 18
5 9.5 19 24
6 11.5 23 28.5
$ bash x.awk 3
# col1 col2 col3
1 2 8 10
2 5 11 13
3 8 16 19.3333
4 11 22 27.6667
$ bash x.awk 4
# col1 col2 col3
1 2.5 8.5 10.5
2 6.5 13.25 15.75
3 10.5 21 26.25
$ bash x.awk 6
# col1 col2 col3
1 3.5 9.5 11.5
2 9.5 19 23.5
$
如果您希望在末尾打印出部分组,请添加一个适当的END
块,该块需要除以部分行数而不是行数。
答案 1 :(得分:1)
我冒昧地将Jonathan Leffler的答案概括为Nth
案例,以了解平均窗口和偏移量的大小。
我写了一个awk
脚本(我称之为avewithoffset
),如下所示:
#!bin/awk
BEGIN{
FS=OFS="\t";
n=5; }
NR==1 { print; next;}
(NR-1)%n!=0 { for (i = 2; i <= NF; i++) old[i] += $i; }
(NR-1)%n==0 { for (i = 2; i <= NF; i++)
{ $i = ($i + old[i])/n; old[i] = 0; }
$1 = int( (NR-1)/n );
print; }
注意 n=5
。
我将以下文件提供给它:
# col1 col2 col3
1 1 16 31
2 2 17 32
3 3 18 33
4 4 19 34
5 5 20 35
6 6 21 36
7 7 22 37
8 8 23 38
9 9 24 39
10 10 25 40
11 11 26 41
12 12 27 42
13 13 28 43
14 14 29 44
15 15 30 45
结果文件如下:
# col1 col2 col3
1 3 18 33
2 8 23 38
3 13 28 43