我有三个 csv 文件,每个文件都包含获取第四个文件所需的信息。我正在描述玩具文件,但实际文件包含更多的列和行,仍然在相同的模型上。
文件 1 是原始数据文件。 “个人”中的每个“rs”都有一个字母。例如。 individual0 在 rs009 中具有“A”,在 rs888 中具有“T”等。 :
Individual0 Individual1 Individual2 Individual3
rs009 A T A A
rs888 T T T T
rs103 C C C C
rs591 A A A A
rs112 A A A A
rs004 C C C C
文件 2 将“rs”变量聚集在“组”中。每个“组”都是连续“rs”变量的组合,按照文件 1 中的顺序排列。例如,rs009 和 rs103 聚集在名为“Group0”的变量中。不可能有“组”当“Group0”结束时,“Group1”开始,等等。重要的是,一些“rs”变量在这一步被过滤掉(即rs888):
Group0 rs009 rs103
Group1 rs591 rs112 rs004
文件 3 是结果文件,其中每个“组”变量都会为每个“个人”分配一个编号。例如,Individual2 在其 Group0 中有一个 3,在其 Group1 中有一个 2:
Individual0 Individual1 Individual2 Individual3
Group0 1 3 3 3
Group1 3 3 2 3
我想要获取的文件与文件 1 类似,但其中对于文件 3 中给定的“个人”,不在“组”= 3 中的所有“rs”变量将设置为 0,而其他人会保留他们的信。例如,rs009属于Group0(参见文件2),那么文件3告诉Individual0的Group0有一个“1”,这意味着文件1中提到的字母应该更改为0。相反,对于Individual1,文件 3 表明 Group0 有一个“3”,因此应保留 File1 中的字母(即“T”)。被过滤掉的“rs”变量将获得与列表中前一个变量相同的编号(即 rs888 与 rs009 具有相同的“组”分配):
Individual0 Individual1 Individual2 Individual3
rs009 0 T A A
rs888 0 T T T
rs103 0 C C C
rs591 A A 0 A
rs112 A A 0 A
rs004 C C 0 C
换句话说,我需要:
1)获取文件1
2) 检查文件 2 中每个 'rs' 属于哪个 'Group'。如果 'rs' 不在 File2 中,则根据 File1 中的顺序,它与前一个 'rs' 属于同一“Group” 。
3) 获取为文件 3 中每个“个人”中的每个“组”分配的值
4) 如果后一个值为“3”,则保留为文件 1 中每个“个体”分配的字母 (A/C/G/T),否则将其更改为“0”
我用 awk 尝试了几种选择,但我的知识相当有限,所以我无法找出最终获得我需要的东西的方法。这是我的第一篇文章,所以我希望提供足够的信息。我可以运行 Perl 脚本,但恐怕不会编写它。在此先感谢您的帮助 !
答案1
好吧,这是一个黑客,但无论如何:
让我们使用file3
andfile2
并将这些组解析为一个中间文件resolved
,如下所示:
awk '
FNR == NR {
group = $1
$1 = ""
groups[group] = $0
}
FNR != NR {
for (i = 2; i <= NF; i++) {
print $i" "groups[$1]
}
}
' <(tail -n+2 file3) file2 > resolved
到:
$ cat resolved
rs009 1 3 3 3
rs103 1 3 3 3
rs591 3 3 2 3
rs112 3 3 2 3
rs004 3 3 2 3
然后将resolved
其与 with 结合使用file1
:
awk '
FNR == NR {
group = $1;
for (i = 2; i <= NF; i++) {
groups[group][i] = $i
}
}
FNR != NR {
if ($1 in groups) {
group = $1
}
for (i = 2; i <= NF; i++) {
if (groups[group][i] != 3) {
$i = 0
}
}
print
}
' resolved <(tail -n+2 file1)
其产生:
rs009 0 T A A
rs888 0 T T T
rs103 0 C C C
rs591 A A 0 A
rs112 A A 0 A
rs004 C C 0 C
利用column
并添加回标头,我们就可以了。