我有一个用空格分隔的大文件,其中包含成千上万的行和列。如果值的行数少于5,我想将其转换为N.A。
输入:
CHROM 108 139 159 265 350 450 461 559 765 850
SNP1 0 0 0 0 0 0 2 2 2 2
SNP2 2 2 2 2 2 0 0 0 0 0
SNP3 -1 -1 -1 -1 0 0 0 0 0 0
SNP4 0 0 0 -1 -1 2 2 2 2 2
SNP5 1 1 1 1 1 1 0 0 0 0
输出:
CHROM 108 139 159 265 350 450 461 559 765 850
SNP1 0 0 0 0 0 0 N.A N.A N.A N.A
SNP2 2 2 2 2 2 0 0 0 0 0
SNP3 N.A N.A N.A N.A 0 0 0 0 0 0
SNP4 N.A N.A N.A N.A N.A 2 2 2 2 2
SNP5 1 1 1 1 1 1 N.A N.A N.A N.A
我正在使用以下命令来实现所需的输出:
计算零计数:
awk -F'|' 'BEGIN{print "count", "lineNum"}{print gsub(/0/,"") "\t" NR}' input_ > output_1
提取计数列:
awk '{print $1}' output_1 > output_1_col_1
与原始文件合并计数:
paste -d " " output_1_col_1 original_file > output_2
将值转换为计数少于5的N.A:
awk '$1 < 6{gsub("0","N.A")}1' output_2 > Final_output
类似地,我重复这些步骤来计算1、2和-1的计数。
有没有更好更快的方法来获得所需的输出?
答案 0 :(得分:3)
通过文件一次:仍然需要遍历两次字段。
awk '
FNR > 1 {
delete count
for (i=2; i<=NF; i++) count[$i]++
for (i=2; i<=NF; i++) if (count[$i] < 5) $i = "N.A"
}
1
' file | column -t
答案 1 :(得分:2)
请您尝试以下。
awk '
FNR==1{
if(++count==1){
print
}
next
}
FNR==NR{
for(i=2;i<=NF;i++){
a[FNR,$i]++
}
next
}
{
for(i=2;i<=NF;i++){
$i=a[FNR,$i]<5?"N.A":$i
}
}
1
' Input_file Input_file
输出如下。
CHROM 108 139 159 265 350 450 461 559 765 850
SNP1 0 0 0 0 0 0 N.A N.A N.A N.A
SNP2 2 2 2 2 2 0 0 0 0 0
SNP3 N.A N.A N.A N.A 0 0 0 0 0 0
SNP4 N.A N.A N.A N.A N.A 2 2 2 2 2
SNP5 1 1 1 1 1 1 N.A N.A N.A N.A