如何计算csv中列子集的平均值?

How to calculate average of subsets of columns in csv?

我有一个非常大的 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

对于所有列,我想计算每个连续两个字段的平均值,然后偏移到下两个字段。例如,在 col112 的平均值是结果列的 第一个 单元格,33 的平均值4 是结果列的 second 单元格。因此,新的列大小是原始 col1.

一半

对于上面提供的示例文件,脚本的输出应如下所示:

#       col1    col2    col3
1       1.5     7.5     9.5
2       3.5     9.5     11.5
3       5.5     11.5    13.5

这个问题似乎是一个可以用 AWK 解决的好[问题],但我对使用 AWK 还是个新手。

不胜感激。

可以用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
                = (NR-1)/2; print }'
  1. 将输出字段分隔符设置为制表符。
  2. 打印 header 行并跳到下一行。
  3. 对于偶数行,将字段 2 中的值保存到 old 数组的末尾。
  4. 对于奇数行(第一行之后),计算旧字段值和当前字段值的平均值。设置行号。打印结果。

示例输出:

#       col1    col2    col3
1       1.5     7.5     9.5
2       3.5     9.5     11.5
3       5.5     11.5    13.5

对 N 行的组进行泛化

此脚本接受一个参数,该参数是要组合在一起的行数,如果未指定参数则默认为 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
                = 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块,它需要除以部分行数而不是行数。

我冒昧地概括了 Jonathan Leffler 的回答,以涵盖 Nth 大小的平均值 window 和偏移量的情况。

我写了一个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; }
               = 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