如何将一列中的值除以另一列并在新列中打印结果?

时间:2017-06-14 20:06:03

标签: linux awk text-processing

我对awk比较新,所以我有一个关于分割的简单问题,并在新专栏中打印结果。例如:

head data

1   13273      .  G   C   563  5  .  25    128
1   202259     .  G   T   675  8  .  12    130
1   598934     .  C   C   756  9  .  17    231
1   634112     .  T   C   125  1  .  32    89
1   779762     .  G   A   675  5  .  28    187

我想将第9列除以第10列,并将结果打印在新列11中,最好将新结果从高到低排序。例如:

1   634112     .  T   C   125  1  .  32    89    0.360
1   13273      .  G   C   563  5  .  25    128   0.195
1   779762     .  G   A   675  5  .  28    187   0.150
1   202259     .  G   T   675  8  .  12    130   0.092
1   598934     .  C   C   756  9  .  17    231   0.074

我只知道如何在R中执行此操作,但我想了解如何在awk中执行此操作。谢谢!

2 个答案:

答案 0 :(得分:2)

Awk对于第一个要求非常有表现力。如果你想要一个第11列,你可以发明它并将它设置为等于第9列除以第10列的结果。

可以在awk中进行排序,但是只需管道排序就会有点麻烦。 column命令使它更漂亮,仅此而已。

$ awk '{$11 = $9 / $10}1' file | sort -nr -k 11 | column -t
1  634112  .  T  C  125  1  .  32  89   0.359551
1  13273   .  G  C  563  5  .  25  128  0.195312
1  779762  .  G  A  675  5  .  28  187  0.149733
1  202259  .  G  T  675  8  .  12  130  0.0923077
1  598934  .  C  C  756  9  .  17  231  0.0735931

如果输出需要以制表符分隔,则可以设置OFS变量(并忘记列命令):

$ awk -v OFS='\t' '{$11 = $9 / $10}1' file | sort -nr -k 11 
1   634112  .   T   C   125 1   .   32  89  0.359551
1   13273   .   G   C   563 5   .   25  128 0.195312
1   779762  .   G   A   675 5   .   28  187 0.149733
1   202259  .   G   T   675 8   .   12  130 0.0923077
1   598934  .   C   C   756 9   .   17  231 0.0735931

最后,您可以使用sprintf格式化示例输出中的最后一列:

$ awk -v OFS='\t' '{$11 = sprintf("%.3f", $9 / $10)}1' file | sort -nr -k 11
1   634112  .   T   C   125 1   .   32  89  0.360
1   13273   .   G   C   563 5   .   25  128 0.195
1   779762  .   G   A   675 5   .   28  187 0.150
1   202259  .   G   T   675 8   .   12  130 0.092
1   598934  .   C   C   756 9   .   17  231 0.074

<强>更新

正如Ed Morton在他的回答中所示,三元运算符?:可用于防止被零除。我在这里放了&#34; UND&#34;在第11栏中指出&#34; undefined&#34;,但当然你可以把它留空或放一些不同的价值。

$ awk -v OFS='\t' '{$11 = ($10 != 0) ? sprintf("%.3f", $9 / $10) : "UND"}1' file | sort -nr -k 11
1   634112  .   T   C   125 1   .   32  89  0.360
1   13273   .   G   C   563 5   .   25  128 0.195
1   779762  .   G   A   675 5   .   28  187 0.150
1   202259  .   G   T   675 8   .   12  130 0.092
1   598934  .   C   C   756 9   .   17  0   UND

在某些时候,您可能会认为awk程序变得足够复杂,以至于它在自己的文件中更好,重点在于可读性而不是紧凑性。

$ cat div.awk file 

BEGIN { OFS="\t"}

{
    if ($10 != 0) {
        quotient = $9 / $10
        $11 = sprintf("%.3f", quotient)
    }
    else {
        $11 = "UND"
    }
    print
}


$ awk -f div.awk file  | sort -nr -k 11
1   634112  .   T   C   125 1   .   32  89  0.360
1   13273   .   G   C   563 5   .   25  128 0.195
1   779762  .   G   A   675 5   .   28  187 0.150
1   202259  .   G   T   675 8   .   12  130 0.092
1   598934  .   C   C   756 9   .   17  0   UND

答案 1 :(得分:2)

使用GNU awk for sorted_in:

belongs_to

如果$ 10可以为零,则将$ cat tst.awk { a[NR]=$0; v[NR]=$9/$10 } END { PROCINFO["sorted_in"]="@val_num_desc" for (i in v) { print a[i] "\t" v[i] } } $ awk -f tst.awk file 1 634112 . T C 125 1 . 32 89 0.359551 1 13273 . G C 563 5 . 25 128 0.195312 1 779762 . G A 675 5 . 28 187 0.149733 1 202259 . G T 675 8 . 12 130 0.0923077 1 598934 . C C 756 9 . 17 231 0.0735931 更改为v[NR]=$9/$10或类似内容以防止被零除。