for 循环中的 If 运算符

If operator inside for loop

我有如下输入文件,需要对每 3 列三元组进行此转换col1*0 + col2*1 + col3*2

input.txt - 所有正数,可以是小数,真实文件有 1000 列。

0 0 0 1 0 0
0 1 0 0 0 1
0 0 1 0 0 0

我有下面的 gawk 行:

gawk '{for(i=1;i<=NF;i+=3)x=(x?x FS:"")(($(i+1))+($(i+2)*2));print x;x=y}' input.txt
0 0
1 2
2 0

此外,我需要检查3个数字是否全为零,如果全为零则转换应该是-9

伪代码:

if($i==0 & $(i+1)==0 & $(i+2)==0) {-9} else {$(i+1)+$(i+2)*2}
#or as all numbers are positive.
if(($i+$(i+1)+$(i+2))==0) {-9} else {$(i+1)+$(i+2)*2}

预期输出:

-9 0
1 2
2 -9

资料说明: 此数据是从 IMPUTE2 software - a genotype imputation and haplotype phasing program. Rows are SNPs 输出的,列是样本。每个 SNP 由 3 列表示。每个 SNP 有 3 个数字,范围为 0-1(等位基因 AA AB BB 的概率)。所以在上面的例子中我们有 3 个 SNP 和 2 个样本。插补也可以表示为剂量值,每个 SNP 1 个数字,范围为 0-2。我们正在尝试将概率格式转换为剂量格式。当 IMPUTE2 不能给任何等位基因任何概率时,它输出为 0 0 0,那么我们应该转换为 no call -9.

如果给定的三个列是 0,您希望总和不同。为此,您可以将三元运算符扩展为 >

gawk '{ for(i=1;i<=NF;i+=3) {
          x=$(i+1) + $(i+2)*2;   # the sum
          res=res (res ? FS : "") ($i==0 && $(i+1)==0 && $(i+2)==0 ?-9:x)
        }
       print res; res=""         # print stored line and empty for next loop
      }' file

即如果所有元素都是0,则追加值-9。否则,计算出的 x:

res=res (res ? FS : "") ($i==0 && $(i+1)==0 && $(i+2)==0 ?-9:x)
                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^   ^
                           if three columns are 0..........|

如果所有值都是正数,则可以重新格式化检查以仅比较总和是否为 0

($i + $(i+1) + $(i+2)) ? x : -9

用你的文件测试显然有效:

$ gawk '{for(i=1;i<=NF;i+=3) {x=$(i+1) + $(i+2)*2; res=res (res ? FS : "") ($i==0 && $(i+1)==0 && $(i+2)==0 ?-9:x)} print res; res=""}' file
-9 0
1 2
2 -9

另一个awk单行(假设非负输入值)

$ awk '{c1=+2*;c2=+2*; print c1||?c1:-9,c2||?c2:-9}' lop
-9 0
1 2
2 -9