【发布时间】:2019-08-27 11:43:31
【问题描述】:
我正在尝试使用 awk 替换文件中多个列的值。使用 awk 的原因是文件非常大,无法将其加载到内存中。我试过用熊猫(python)做。
我有一个大型数据库作为文本文件。我在这里放了一个文件中的信息示例(制表符分隔):
CHROM POS REF ALT GT_00 d_GT_00 c_GT_00 de_GT_00 can_GT_00 epi_GT_00
chr1 10 T A 7 1 1 2 5 7
chr1 10 T A 7 1 1 3 0 1
chr1 10 T G 7 2 1 1 8 2
chr1 11 None None 2 0 0 0 5 4
chr1 11 G T 2 1 0 0 2 3
如果行中的前两列 (CHROM,POS) 相同,我必须对标题中包含“_00”的列的值求和。
所以,预期的输出是:
CHROM POS REF ALT GT_00 d_GT_00 c_GT_00 de_GT_00 can_GT_00 epi_GT_00
chr1 10 T A 21 4 3 6 13 10
chr1 10 T A 21 4 3 6 13 10
chr1 10 T G 21 4 3 6 13 10
chr1 11 None None 4 1 0 0 7 7
chr1 11 G T 4 1 0 0 7 7
我不知道该怎么做,因为我是编程新手,所以,我必须用这个awk代码做以下事情。
awk -F'\t' 'FNR==1{next};
{keys[$1"\t"$2]
for (i=5;i<=10;i++)
{sum[$1"\t"$2, i] += $i}
}END {for (key in keys) { printf "%s", key
for (i=5;i<=10;i++) {printf "%s%s", "\t", sum[key,i]} printf "\n"}} OFS='\t' out.txt
使用此代码,并将第一个文本文件用作“out.txt”,我得到:
chr1 10 21 4 3 6 13 10
chr1 11 4 1 0 0 7 7
现在,我正在尝试替换带有chr1 10 的行中的第一行中的6 个值,以及带有chr1 11 的行中的第二行中的6 个值。
我已经完成了使用此代码更改一列中的值:
awk -F"\t" 'NR==FNR{h[$1"\t"$2]=$3;next}
{
printf $1"\t"$2"\t"$3"\t"$4"\t"h[$1"\t"$2]"\t";
for (i=6;i<=NF;i++)
{printf "%s",$i "\t"};
printf "\n"
}' OFS="\t" file1 file2
但需要对所有列执行相同操作。
我怎样才能使用类似的代码来做到这一点?
注意:我有更多列的标题名称中没有“_00”
【问题讨论】:
-
好吧,如果你有datamash,试试这个
datamash -H -g1,2 collapse 3,4 sum 5-10 <your_file -
@oguzismail 感谢您的回答!我已经尝试过了,它似乎只将 chr1 10 的三个值中的两个相加
-
@oguzismail 忘记我说过的话,我在使用没有标题的文件时保留了 -H。它完美地工作!有没有办法撤消折叠并获得具有最终总和值的所有行?
-
我不太了解datamash,但您可以使用awk 撤消折叠,只需将datamash 的输出通过管道传输到
awk 'BEGIN{FS=OFS="\t"} {j=split($3,a,",");split($4,b,",");for(i=1;i<=j;++i){$3=a[i];$4=b[i];print}}' -
你好@oguzismail!您知道是否可以对一系列列进行拆分?在我的真实数据中,我有大约 80 列要折叠,而且写
split($n,a,",") and $n=a[i]80 次非常肮脏且不优雅。我试图嵌套两个for循环:1.迭代折叠的列,2.将值迭代到数组'a'中,但无法获得期望的结果