有两个输入文件;两者都格式化为 TSV。
File1: treated.bam.tsv
File2: untreated.bam.tsv
两个文件具有相同的字段,如下所列。 (出于演示目的,我进行了编号)——每个文件有 23 个字段。
1chrom 9mismatches_pp 17C_pp
2pos 10deletions 18T
3ref 11deletions_pp 19T_pp
4reads_all 12insertions 20G
5reads_pp 13insertions_pp 21G_pp
6matches 14A 22N
7matches_pp 15A_pp 23N_pp
8mismatches 16C
如果两个文件中第一列和第二列(chrom、pos)中的值相同,我想提取记录中的一些字段,然后创建一个如下所示的新输出文件。输出文件有 15 个字段,组合了两个输入文件的数据,如下所示。
From file1:
1chrom
2pos
3ref
4reads_all
8mismatches
10deletions
12insertions
pct_file1 (the values from file1: (8mismatches+10deletions+12insertions)/4reads_all)
From file2:
3ref
4reads_all
8mismatches
10deletions
12insertions
pct_file2 (the values from file2: (8mismatches+10deletions+12insertions)/4reads_all)
-New values from extractions.
pct_sub (the values from pct_file1 - pct_file2: ((8mismatches+10deletions+12insertions)/4reads_all) - ((8mismatches+10deletions+12insertions)/4reads_all))
在输出文件中,前八列来自File1,treated.bam.tsv
(第8列是从File1中使用8mismatches、10deletions、12insertions和4reads_all计算得到的值)。
其余的来自File2,untreated.bam.tsv
第13列也是根据File2的8mismatches、10deletions、12insertions和4reads_all计算得到的值。
最后一个字段pct_sub
是根据 File1 ((8mismatches+10deletions+12insertions)/4reads_all) 和 File2 ((8mismatches+10deletions+12insertions)/4reads_all) 中的字段的减值计算得出的。
如何在输出文件中添加新的列名称,例如pct_file1
, pct_file2
, pct_sub
?
这是我为上面的输出文件所做的。 (输入和输出文件均具有相同的格式:TSV。)
awk 'FNR==NR{array[$1,$2]=$0;next} { if ( $1 $2 in array ) print $1, $2, array[$3], array[$4], array[$8], array[$10], array[$12], (array[$8]+array[$10]+array[$12])/array[$4], $3, $4, $8, $10, $12, ($8+$10+$12)/$4, ((array[$8]+array[$10]+array[$12])/array[$4])-(($8+$10+$12)/$4) > "awkoutput.bam.tsv" }' treated.bam.tsv untreated.bam.tsv
(Actually, $1, $2 are not a problem from File1 or File2)
文件1 ( treated
)
chrom pos ref reads_all reads_pp matches matches_pp mismatches mismatches_pp deletions deletions_pp insertions insertions_pp A A_pp C C_pp T T_pp G G_pp N N_pp
chrY 59363551 G 8 0 7 0 0 0 1 0 5 0 0 0 0 0 0 0 7 0 0 0
chrY 59363552 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0
chrY 59363553 T 7 0 7 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0
chrY 59363554 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0
chrY 59363555 T 7 0 7 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0 0 0
文件2 ( untreated
)
chrom pos ref reads_all reads_pp matches matches_pp mismatches mismatches_pp deletions deletions_pp insertions insertions_pp A A_pp C C_pp T T_pp G G_pp N N_pp
chrY 59363551 G 2 0 2 0 0 0 0 0 1 0 0 0 0 0 0 0 2 0 0 0
chrY 59363552 G 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
chrY 59363553 T 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
chrY 59363554 G 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0
chrY 59363555 T 1 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
输出
chrom pos ref reads_all mismatches deletions insertions pct_file1 ref reads_all mismatches deletions insertions pct_file2 pct_sub
chrY 59363551 G 8 0 1 5 0.75 G 2 0 0 1 0.5 0.25
chrY 59363552 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363553 T 7 0 0 0 0 T 1 0 0 0 0 0
chrY 59363554 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363555 T 7 0 0 0 0 T 1 0 0 0 0 0
答案1
生物信息学似乎很有趣。如果您对非 awk 解决方案持开放态度,那么这对您来说很容易miller
:
mlr --itsv join -u -j chrom,pos --lp tr_ --rp untr_ -f treated.bam.tsv untreated.bam.tsv | # join data from treated and untreated files by fields chrom and pos
mlr put '$tr_pct=($tr_mismatches+$tr_deletions+$tr_insertions)/$tr_reads_all' | # calculate pct for treated data
mlr put '$untr_pct=($untr_mismatches+$untr_deletions+$untr_insertions)/$untr_reads_all' | # calculate pct for untreated data
mlr cut -o -f chrom,pos,tr_ref,tr_reads_all,tr_mismatches,tr_deletions,tr_insertions,tr_pct,untr_ref,untr_reads_all,untr_mismatches,untr_deletions,untr_insertions,untr_pct | # remove superfluous fields
mlr --otsv put '$pct_sub=$tr_pct-$untr_pct' # append pct subtraction field
chrom pos tr_ref tr_reads_all tr_mismatches tr_deletions tr_insertions tr_pct untr_ref untr_reads_all untr_mismatches untr_deletions untr_insertions untr_pct pct_sub
chrY 59363551 G 8 0 1 5 0.750000 G 2 0 0 1 0.500000 0.250000
chrY 59363552 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363553 T 7 0 0 0 0 T 1 0 0 0 0 0
chrY 59363554 G 7 0 0 0 0 G 1 0 0 0 0 0
chrY 59363555 T 7 0 0 0 0 T 1 0 0 0 0 0
它看起来比实际更可怕。真的。
答案2
if ( $1 $2 in array )
不起作用;你必须做if (($1,$2) in array)
。- 你不能使用
array[$3]
和array[$4]
喜欢那样。你的数组看起来像数组[chrY,59363551]=“chrY 59363551 G 8 0 7 0 0 0 1 0 5 0 0 0 0 0 0 0 7 0 0 0” 数组[chrY,59363552]=“chrY 59363552 G 7 0 7 0 0 0 0 0 0 0 0 0 0 0 0 0 7 0 0 0” ︙
当你说array[$3]
and时array[$4]
,你指的是array[G]
andarray[2]
等,它们不存在。 - 当您想要写入多个文件时,在代码中指定的能力是一个很棒的功能。当您只有一个输出文件时,它就没那么有用了——为什么不直接重定向命令的输出呢?
> "filename"
awk
awk
- 排长队是不好的。将长命令分成短行。通过重用变量来减少重复。
- 不要使用数组称为
array
。这就像有一个名为 的变量variable
、一个名为 的文件file
、一个名为 的人Person
等。使用描述性名称。
好吧,就是说,
awk 'FNR==NR {file1data[$1,$2]=$0; next}
{ if (($1,$2) in file1data) {
# Save desired values from file2.
file2arg03=$3
file2arg04=$4
file2arg08=$8
file2arg10=$10
file2arg12=$12
pct_file2=($8+$10+$12)/$4
# Get data from file1.
$0=file1data[$1,$2]
pct_file1=($8+$10+$12)/$4
print $1, $2, $3, $4, $8, $10, $12, pct_file1, \
file2arg03, file2arg04, file2arg08, file2arg10, file2arg12, \
pct_file2, pct_file1-pct_file2
} else printf "(%s,%s) in file2 but not file1.%s", $1, $2, ORS
}' treated.bam.tsv untreated.bam.tsv > awkoutput.bam.tsv
与您的版本一样,这会将 file1 数据保存在数组中,然后在读取 file2 时执行所有工作/输出。从 file2 接收到一行后,它将该行中所需的字段保存到命名变量中(我们也可以使用另一个数组,五个元素长)
进而它从 file1 中的相应行恢复数据。通过将整行分配给$0
,它会导致$1
、$2
、$3
、$4
等恢复为其原始值。
您在输出中写入标题行真的有问题吗?尝试:
{ if (FNR == 1) {
print "chrom pos ref reads_all mismatches deletions insertions pct_file1 …"
} else if (($1,$2) in file1data ) {
file2arg03=$3
︙
好的,这是一个在精神上更接近您的尝试的版本,并且处理标题行:
awk 'FNR==NR {file1line[$1,$2]=$0; next}
{ if (FNR == 1) {
print "chrom pos ref reads_all mismatches deletions insertions pct_file1 ref reads_all mismatches deletions insertions pct_file2 pct_sub …"
} else if (($1,$2) in file1line ) {
# Get data from file1.
split(file1line[$1,$2], file1arg)
pct_file1=(file1arg[8]+file1arg[10]+file1arg[12])/file1arg[4]
pct_file2=($8+$10+$12)/$4
print $1, $2, file1arg[3], file1arg[4], file1arg[8], \
file1arg[10], file1arg[12], pct_file1, \
$3, $4, $8, $10, $12, pct_file2, pct_file1-pct_file2
} else printf "(%s,%s) in file2 but not file1.%s", $1, $2, ORS
}' treated.bam.tsv untreated.bam.tsv > awkoutput.bam.tsv
file1line
这会从 file1(来自)检索该行,并将其传递给split
将其分解为 23 个组成值,这些值存储在数组 中file1arg
。然后它就可以像您使用file1arg[3]
, file1arg[4]
, ... 一样使用array[$3]
, array[$4]
, ...