使用awk连续元素的移动平均值

时间:2016-08-04 10:41:02

标签: bash awk

我正在尝试编写一个脚本,其中每个行元素将给出接下来N行(包括其自身)的平均值。我知道如何使用前面的行,如第N行将给出前面N行的平均值。这是

的脚本
awk '
BEGIN{
       N = 5;
     }

     { 
       x = $2;
       i = NR % N;
       aveg += (x - X[i]) / N;
       X[i] = x;
       print $1, $2, aveg; 
     }' < file > aveg.txt

文件看起来像这样

     1       1
     2       2
     3       3
     4       4
     5       5
     6       6
     7       7
     8       8
     9       9
    10      10
    11      11
    12      12
    13      13
    14      14
    15      15
    16      16
    17      17
    18      18
    19      19
    20      20
    21      21
    22      22
    23      23
    24      24
    25      25
    26      26
    27      27
    28      28
    29      29
    30      30
    31      31
    32      32
    33      33
    34      34
    35      35
    36      36
    37      37
    38      38
    39      39
    40      40

我希望第一行具有接下来的5个元素的平均值,即

 (1+2+3+4+5)/5=3
 second row (2+3+4+5+6)/5=4
 third row  (3+4+5+6+7)/5=5

等等。行应该看起来像

    1        1       3  
    2        2       4
    3        3       5
    4        4       6   ...

可以像上面显示的脚本一样简单地完成吗?我在考虑将行值指定为下面第n行的值,然后继续上面的脚本。但是,遗憾的是,我无法将行值分配给文件中的某个值。有人可以帮我写这个脚本并找到移动平均线。我也对shell中的其他命令持开放态度。

3 个答案:

答案 0 :(得分:5)

$ cat test.awk
BEGIN {
    N=5            # the window size
}
{
    n[NR]=$1       # store the value in an array
} 
NR>=N {            # for records where NR >= N
    x=0            # reset the sum variable
    delete n[NR-N] # delete the one out the window of N
    for(i in n)    # all array elements
        x+=n[i]    # ... must be summed
    print n[NR-(N-1)],x/N  # print the row from the beginning of window
}                          # and the related window average

试一试:

$ for i in {1..36}; do echo $i $i >> test.in ; done
$ awk -f test.awk test.in
1 3
2 4
3 5
...
30 32
31 33
32 34

可以在运行总和,添加当前和减去n[NR-N]中完成,如下所示:

BEGIN {
    N=5
} 
{
    n[NR]=$1
    x+=$1-n[NR-N]
} 
NR>=N {
    delete n[NR-N]
    print n[NR-(N-1)],x/N
}

答案 1 :(得分:1)

使用N尺寸的数组

BEGIN { N=5 }

{
  s+=array[i++]=$1

  if (i>=N) i=0
}

NR>=N {
        print array[i], s/N
        s-=array[i]
}

答案 2 :(得分:1)

$ cat tst.awk
BEGIN { OFS="\t"; range=5 }
{ recs[NR%range] = $0 }
NR >= range {
    sum = 0
    for (i in recs) {
        split(recs[i],flds)
        sum += flds[2]
    }
    print recs[(NR+1-range)%range], sum / range
}

$ awk -f tst.awk file
1       1       3
2       2       4
3       3       5
4       4       6
5       5       7
6       6       8
7       7       9
8       8       10
9       9       11
10      10      12
11      11      13
12      12      14
13      13      15
14      14      16
15      15      17
16      16      18
17      17      19
18      18      20
19      19      21
20      20      22
21      21      23
22      22      24
23      23      25
24      24      26
25      25      27
26      26      28
27      27      29
28      28      30
29      29      31
30      30      32
31      31      33
32      32      34
33      33      35
34      34      36
35      35      37
36      36      38