当行名称与sort不匹配时,内部连接基于unix中的一列的两个文件

时间:2017-12-21 15:38:11

标签: python r unix awk

我遇到了尝试在unix中加入两个数据集的问题,可以使用你的帮助。我花了很长时间在论坛上寻找解决方案但空手而归。

我在一个数据集中有一个入藏号列表,需要将它们转换为基因符号。为此,我下载了gene2accession.gz from NCBI。未压缩的文件大约是7Gb,所以首先我从这个数据集中删除了加入和基因符号

cut -f 2,16 gene2accession > accession2genesymbol

根据wc -l accession2genesymbol有大约7000万行,有很多重复,所以我用sort accession2genesymbol | uniq删除了这些行,导致了大约2000万行。

现在通常我会在R中执行inner_join() using the dplyr package(返回x中y匹配值的所有行,以及x和y中的所有列);但是,这个数据集对我来说太大了。

以下是未排序的 accession2genesymbol数据集的示例:

100000492       mafaa
1000004 XCC3444
110047139       LOC110047139
110047140       LOC110047140
9951915         LOAG_14435
9951916         LOAG_14436
999999          gndA
999             CDH1
9               NAT1

未分类的简短示例看起来像这样(对于整个数据集-1,576行see the gist):

Accessions
10047140
100913206
10092617
10190704
10190704
103471987
103471997
103472005
103472005
105990514
45006951
45006986
45006986
45007007
45007007
4501883
4501887
94721250
94721261
9558733
9845516
98986457
98986457
98986464
99028871
9910242
9951915
9966805
9966827
9966867
9994185

编辑:此处仅限加入9951915和110047140有匹配,因此我的预期输出为:

9951915         LOAG_14435
110047140       LOC110047140

对于数据操作/加入没有使用unix我搜索了Stack Overflow类似的问题。

例如this one。我的理解是unix join函数只能在文件排序时使用,所以我尝试了以下内容:

join -t "\t" <(dos2unix <accession) <(dos2unix <accession2genesymbol.txt)

也许这不起作用,因为我需要 完全 两个数据集中的相同行号(即,如果数据集的第100行不匹配第100行)数据集2它不会工作)但也许我错了,而且由于某些其他原因这没有用?

或许awk是更好的解决方案,所以我尝试了this post的建议:

awk '{a[$1]=a[$1] FS $2} END {for (i in a) print i a[i]}' accession accession2genesymbol | sort > file3

这会生成一个包含大约2000万行的文件,因为我的加入只有9000行,所以我希望9000行(例如,如果那些加入不再存在,可能会更少)。

我在第一篇文章中尝试了另一个awk解决方案:

awk -F, 'FNR==NR{a[$1];next}($1 in a){print $2}' accession accession2genesymbol > file3
awk: warning: escape sequence `\+' treated as plain `+'

但我最终得到一个空文件。

我很欣赏awk(病房)解决方案,python或任何可以帮助我解决这个问题的方法。非常感谢你。

2 个答案:

答案 0 :(得分:2)

join适用于您的情况。由于您的输入文件没有匹配,因此这是一个组成示例并使用您的地图文件

$ head file
100000009
100000061
100000030

$ join <(sed 1d map) <(sort file)
100000009 sema5bb+
100000030 btr24+
100000061 si:ch211-133n4.9+

假设您的map文件已经排序,则需要删除标题sed 1d并需要对输入file进行排序。请注意,排序应该是数字或词汇。

另一种不需要排序的替代方法是使用grep

$ grep -wFf file map
100000009       sema5bb+
100000030       btr24+
100000061       si:ch211-133n4.9+

如果数字和代码的格式不同,则不会出现错误匹配。

答案 1 :(得分:1)

我们还没有看到原始gene2accession文件的示例,但我们假设它是一个以制表符分隔的字段,第二列为accession,第16列为gene(自这是您的cut选择的)标题行。我们还假设您的Accessions文件并非绝对巨大。

鉴于此,这个脚本应该做你想要的:

awk -F'\t' 'NR==FNR{a[$1];next} ($2 in a) && !seen[$2]++{print $2, $16}' Accessions gene2accession

但是你可以试试看它是否更快:

awk -F'\t' 'NR==FNR{a[$1];next} $2 in a{print $2, $16}' Accessions <(sort -u -t'\t' -k2,2 gene2accession)

如果是,并且您希望在后续运行中使用sort输出的中间文件:

sort -u -t'\t' -k2,2 gene2accession > unq_gene2accession &&
awk -F'\t' 'NR==FNR{a[$1];next} $2 in a{print $2, $16}' Accessions unq_gene2accession