Dad*_*ang 7 shell terminal join bioinformatics
我有这样的file1:
CHR SNP TEST A1 A2 GENO O(HET) E(HET) P
0 AFFX-SNP-000541 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-000541 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-000541 UNAFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-002255 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 UNAFF 0 0 0/0/0 nan nan NA
1 rs12103 ALL C T 55/250/317 0.4019 0.4113 0.5596
1 rs12103 AFF C T 0/0/0 nan nan NA
1 rs12103 UNAFF C T 0/0/0 nan nan NA
1 rs12103_1247494 ALL C T 55/250/321 0.3994 0.4097 0.5581
1 rs12103_1247494 AFF C T 0/0/0 nan nan NA
1 rs12103_1247494 UNAFF C T 0/0/0 nan nan NA
Run Code Online (Sandbox Code Playgroud)
和 file2 像:
CHR SNP A1 A2 MAF NCHROBS
0 AFFX-SNP-000541 0 0 NA 0
0 AFFX-SNP-002255 0 0 NA 0
1 rs12103 C T 0.2894 1244
1 rs12103_1247494 C T 0.2875 1252
Run Code Online (Sandbox Code Playgroud)
我想根据 SNP 名称和 TEST==ALL 将 file2 与 file1 合并,并在输出 file3 中保留 CHR、SNP、P 和 MAF。有人知道在终端(Unix)shell 中最好的方法吗?
所需的输出是:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
Run Code Online (Sandbox Code Playgroud)
在这个答案的帮助下
awk 'FNR==NR && FNR>1 {a[$2] = $5; next}
FNR > 1 && ($2 in a) && $3 == "ALL" {
print $1 " " $2 " " a[$2] " " $9
}' file2 file1
Run Code Online (Sandbox Code Playgroud)
要获得标题,只需将其添加到脚本的开头:
BEGIN{print "CHR SNP MAF P"}
Run Code Online (Sandbox Code Playgroud)
解释:
首先,当两个文件传递给awk时,它们是一个接一个地处理的。这里有两个重要的变量:NR是awk命令开头FNR的行号,以及当前文件开头的行号。即当第一个文件被处理时(这里是file2),NR并且FNR有相同的值,也就是当前处理的行的值。但是当 awk 传递给第二个文件时,它FNR被重置为 1,因此NR和FNR不再相同。因此,测试FNR==NR是了解处理的文件是否是第一个的技巧。
那么让我们看看代码。条件FNR==NR && FNR>1测试我们是否正在处理第一个文件而不是第一行。如果是这种情况,我们将第五列 ( MAF)的值存储在由第二列 ( ) 索引的数组中SNP,然后next语句说要传递到下一行。
当awk处理第二个文件(也就是file1)时,第一个测试为false,这样awk就尝试第二个测试:FNR > 1 && ($2 in a) && $3 == "ALL",即:不是文件的第一行+第二列值(SNP)存在于表中a+第三列值( TEST) 是"ALL"。如果是,则打印第 1 ( CHR)列和第 2 ( SNP) 列,使用 获取MAF数组中的值a[$2],然后打印第 9 列 ( P)。
BEGIN{...}在开头添加一个语句会添加一个仅在处理第一行之前运行的命令。
terdon提到只用 coreutils 做这件事,一个谦虚的建议:
(echo CHR SNP MAF P
paste <(tail -n +2 file2) <(grep ALL file1) |
while read -r chr snp _ _ maf _ _ _ _ _ _ _ _ _ p; do
echo $chr $snp $maf $p;
done) | column -t
Run Code Online (Sandbox Code Playgroud)
输出:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
Run Code Online (Sandbox Code Playgroud)