使用awk查找字段的平均值?

时间:2014-09-16 16:03:17

标签: awk

这就是我想要做的事情:

找到HETATM记录的x,y,z的平均值,x值是7字段,y值是8字段,z值是9字段。

我正在尝试使用此文件http://pastebin.com/EqA2SUMy

执行此操作

以下是样本

  HETATM 1756  O   HOH A 501      -0.923  10.560 127.393  1.00 16.58           O  
 HETATM 1757  O   HOH A 502       9.272  22.148 134.167  1.00 15.08           O  
 HETATM 1758  O   HOH A 503       0.109  20.243 112.094  1.00 20.74           O  
 HETATM 1759  O   HOH A 504      -3.930  10.522 125.779  1.00 20.79           O  
 HETATM 1760  O   HOH A 505      -0.759  36.323  88.018  1.00 17.42           O  
 HETATM 1761  O   HOH A 506      -4.645  51.936  81.852  1.00 21.43           O  
 HETATM 1762  O   HOH A 507      -3.900  17.103 128.596  1.00 14.08           O  
 HETATM 1763  O   HOH A 508       6.834  21.053 135.062  1.00 16.98           O  

任何人都可以告诉我如何为此做一个脚本。

(这部分与评论观众可以忽略)

        ATOM    214  OE2 GLU A 460      -2.959  24.000 103.360  1.00 32.19           O  
     ATOM    215  N   ARG A 461      -5.878  28.748 106.473  1.00 22.68           N  
     ATOM    216  CA  ARG A 461      -6.553  30.043 106.524  1.00 24.34           C  
    ATOM    217  C   ARG A 461      -5.583  31.176 106.219  1.00 22.42           C  
    ATOM    218  O   ARG A 461      -5.918  32.121 105.497  1.00 25.07           O  
   ATOM    219  CB  ARG A 461      -7.222  30.272 107.887  1.00 24.53           C  
   ATOM    220  CG  ARG A 461      -8.425  29.394 108.150  1.00 26.38      

2 个答案:

答案 0 :(得分:1)

$ awk '{for (i=1;i<=3;i++) sum[i]+=$(i+6)}
    END{if (NR) for (i=1;i in sum;i++) print sum[i]/NR}' file
0.25725
23.736
116.62

if (NR)是必要的,以避免空文件上的除零错误。

如果@jaypal是正确的,您只需选择包含HETATM的输入行,然后将其更改为:

awk '/HETATM/{++nr; for (i=1;i<=3;i++) sum[i]+=$(i+6)}
    END{if (nr) for (i=1;i in sum;i++) print sum[i]/nr}' file

答案 1 :(得分:0)

这不是火箭科学。 (更新为仅捕获HETATM记录 - 一个微不足道的更改;如果需要,您可以使用更严格的正则表达式。但是,还需要计算哪些记录匹配并使用该计数,而不是NR,因为您&#39 ;一般来说,忽略了许多记录。)

awk '/HETATM/ { sum7 += $7; sum8 += $8; sum9 += $9; count++ }
     END { if (count > 0)
               printf("avg(x) = %f, avg(y) = %f, avg(z) = %f\n",
                      sum7/count, sum8/count, sum9/count)
     }'

是的,你可以把它全部放在一行但不会那么可读。

我无法回答为什么它会为你制造零点;当运行来自问题的数据时,摇摆线开始而全部,它产生输出:

avg(x) = 0.257250, avg(y) = 23.736000, avg(z) = 116.620125

如果您认为可能存在空输入(或者至少输入中没有HETATM记录)且错误消息不可接受,则可以使用if (count > 0)或等效的保护打印操作(添加到脚本)。如果``count`为零,你可以生成自己喜欢的输出。