如何将一列的值除以另一列并在新列中打印结果?
How to divide values from one column by another and print results in a new column?
我对 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
中实现。谢谢!
Awk 对于第一个要求非常有表现力。如果你想要第 11 列,你可以发明它并将其设置为等于第 9 列除以第 10 列的结果。
可以在 awk 中进行排序,但是通过管道进行排序有点麻烦,所以更容易。 column命令让它更漂亮,仅此而已
$ awk '{ = / }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' '{ = / }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' '{ = sprintf("%.3f", / )}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 在他的回答中所展示的那样,三元运算符 ?:
可用于防止被零除。这里我在第 11 列中放置了 "UND" 以表示 "undefined",当然您可以将其留空或输入其他值。
$ awk -v OFS='\t' '{ = ( != 0) ? sprintf("%.3f", / ) : "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 ( != 0) {
quotient = /
= sprintf("%.3f", quotient)
}
else {
= "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
使用 GNU awk sorted_in:
$ cat tst.awk
{ a[NR]=[=10=]; v[NR]=/ }
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]=/
更改为 v[NR]=(==0 ? 0 : /)
或类似内容以防止 $10 可以为零时被零除。
我对 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
中实现。谢谢!
Awk 对于第一个要求非常有表现力。如果你想要第 11 列,你可以发明它并将其设置为等于第 9 列除以第 10 列的结果。
可以在 awk 中进行排序,但是通过管道进行排序有点麻烦,所以更容易。 column命令让它更漂亮,仅此而已
$ awk '{ = / }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' '{ = / }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' '{ = sprintf("%.3f", / )}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 在他的回答中所展示的那样,三元运算符 ?:
可用于防止被零除。这里我在第 11 列中放置了 "UND" 以表示 "undefined",当然您可以将其留空或输入其他值。
$ awk -v OFS='\t' '{ = ( != 0) ? sprintf("%.3f", / ) : "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 ( != 0) {
quotient = /
= sprintf("%.3f", quotient)
}
else {
= "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
使用 GNU awk sorted_in:
$ cat tst.awk
{ a[NR]=[=10=]; v[NR]=/ }
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]=/
更改为 v[NR]=(==0 ? 0 : /)
或类似内容以防止 $10 可以为零时被零除。