我有一组带有基因型数据的文件,每个文件分为3列数据,包括:MARKER,ID,GENOTYPE。
我想使用AWK(不更改文件的顺序/排序)来执行类似VLOOKUP的命令,以便将文件中的数据连接到单个文件中,如下所示:
File1中:
BIEC2-99962 HOR_233 G_G
BIEC2-9997 HOR_233 A_G
BIEC2-999748 HOR_233 C_C
BIEC2-999848 HOR_233 G_G
BIEC2-99989 HOR_233 A_A
File2:
BIEC2-9997 HOR_250 A_A
BIEC2-999748 HOR_250 C_C
BIEC2-99989 HOR_250 A_C
文件3:
BIEC2-9997 HOR_615 A_G
BIEC2-999748 HOR_615 A_C
BIEC2-999848 HOR_615 A_G
BIEC2-99989 HOR_615 A_C
预期结果:
BIEC2-99962 G_G NA NA
BIEC2-9997 A_G A_A A_G
BIEC2-999748 C_C C_C A_C
BIEC2-999848 G_G NA A_G
BIEC2-99989 A_A A_C A_C
我将不胜感激。
谢谢!
答案 0 :(得分:1)
当在最后一个文件之前甚至不知道标记的存在时插入那些NA并不是完全无关紧要的。没有它,这将是一个单行。
#!/bin/awk
func add_na() {
for (i in a)
if (gsub(/ /, " ", a[i]) < files)
a[i] = a[i] " NA"
}
FNR==1 { add_na(); ++files }
{ a[$1] = a[$1] " " $3 }
END { add_na(); for (i in a) print i a[i] }
add_na
函数查找未在最新文件中显示的标记(即到目前为止输出记录中的空格太少)并向其添加“NA”。
FNR
规则会跟踪我们通过的文件数量,并对NA进行排序
END
规则在打印结果之前添加最后一轮的NA。
答案 1 :(得分:0)
好的,确定不是awk:当涉及复杂类型时,我觉得Perl更舒服......
#!/usr/bin/perl
use strict;
my %out;
my $argc = scalar @ARGV; # @ARGV --> command line arguments
for my $i (1..$argc){ # for all files except the first
open(F,$ARGV[$i]);
while(<F>){
if(/(.*) .* (.*)/){$out{$1}[$i]=$2}
}
}
open(F,$ARGV[0]); # process the first
while(<F>){
if(/(.*) .* (.*)/){
$a=join(" ",map{ $out{$1}[$_] || "NA"} (1..$argc-1));
print "$1 $2 $a\n"}
}
用法:
perl merge-vlookup file1 file2 file3 ... > output
答案 2 :(得分:0)
您可以修改输入集的此脚本:
#!/usr/bin/env python
input_one = '''
BIEC2-99962 HOR_233 G_G
BIEC2-9997 HOR_233 A_G
BIEC2-999748 HOR_233 C_C
BIEC2-999848 HOR_233 G_G
BIEC2-99989 HOR_233 A_A
'''.strip().split()
input_two = '''
BIEC2-9997 HOR_250 A_A
BIEC2-999748 HOR_250 C_C
BIEC2-99989 HOR_250 A_C
'''.strip().split()
input_three = '''
BIEC2-9997 HOR_615 A_G
BIEC2-999748 HOR_615 A_C
BIEC2-999848 HOR_615 A_G
BIEC2-99989 HOR_615 A_C
'''.strip().split()
one_list = input_one[::3]
one_dict = dict(zip(one_list, input_one[2::3]))
two_dict = dict(zip(input_two[::3], input_two[2::3]))
three_dict = dict(zip(input_three[::3], input_three[2::3]))
print '\n'.join([' '.join([k, one_dict[k], two_dict.get(k, 'NA'), three_dict.get(k, 'NA')]) for k in one_list])
输出如下:
$ ./join_test.py
BIEC2-99962 G_G NA NA
BIEC2-9997 A_G A_A A_G
BIEC2-999748 C_C C_C A_C
BIEC2-999848 G_G NA A_G
BIEC2-99989 A_A A_C A_C
这似乎符合您的预期输出。
如果您想了解脚本的工作原理,请在列表理解之前为每个变量使用一些print
语句,然后将列表理解分解为更小的部分。
最终,您可以将列表input_one
,input_two
和input_three
替换为使用open()
和readlines()
方法读取输入文件的结果。< / p>
请记住strip()
和split()
,以便列表中的每个元素与其他元素分开,无论分隔符是空格还是换行符 - 使用print
来调查其中一个元素样本输入列表,如果此要求不清楚。
我认为awk
并不是这项工作的理想工具,我使用它很多。