【问题标题】:How to join (merge) multiple files (by rows) using multiple columns如何使用多列连接(合并)多个文件(按行)
【发布时间】:2018-04-23 16:50:57
【问题描述】:

我有多个文件,内容如下:

==> file1.tab <==
Contig  Position    TS-568_ALLELE   TS-568_FREQUENCY    TS-568_COVERAGE
ch00    11009393    A/C 0.02/0.97   93
ch00    11009395    A/C/T   0.01/0.97/0.01  96
ch00    11009416    A/G/T   0.12/0.83/0.04  97
ch00    11009421    A/G 0.17/0.82   97
ch00    11009427    A/C/T   0.02/0.96/0.00  101
ch01    11009436    C/T 0.99/0.00   103
ch01    11009437    G/T 0.00/0.99   104
ch02    11009441    A/G 0.07/0.92   101
ch02    11009445    G   1.0 96

==> file2.tab <==
Contig  Position    TS-602_ALLELE   TS-602_FREQUENCY    TS-602_COVERAGE
ch00    11009393    C   1.0 7
ch00    11009395    C   1.0 7
ch00    11009416    G   1.0 5
ch00    11009421    G   1.0 5
ch00    11009427    C   1.0 4
ch01    11009436    C   1.0 4
ch01    11009437    T   1.0 4
ch02    11009441    G   1.0 5
ch02    11009445    G   1.0 5

==> file3.tab <==
Contig  Position    TS-586_ALLELE   TS-586_FREQUENCY    TS-586_COVERAGE
ch00    11009393    C   1.0 34
ch00    11009395    C   1.0 35
ch00    11009416    A/G/T   0.07/0.89/0.02  39
ch00    11009421    A/G 0.10/0.89   39
ch00    11009427    A/C 0.02/0.97   37
ch01    11009436    C   1.0 44
ch01    11009437    T   1.0 44
ch02    11009441    A/G 0.06/0.93   45
ch02    11009445    G   1.0 44

我阅读了关于加入 bash 的信息,但我的问题是我需要根据前两个列而不是单个列来加入它们(ch00 11009427 是唯一标识符,ch01 11009427 或 ch03 11009427 也可以在列表)。

所以,预期的输出将是:

==> file_all.tab <==
Contig  Position    TS-568_ALLELE   TS-568_FREQUENCY    TS-568_COVERAGE TS-602_ALLELE   TS-602_FREQUENCY    TS-602_COVERAGE TS-586_ALLELE   TS-586_FREQUENCY    TS-586_COVERAGE
ch00    11009393    A/C 0.02/0.97   93  C   1.0 7   C   1.0 34
ch00    11009395    A/C/T   0.01/0.97/0.01  96  C   1.0 7   C   1.0 35
ch00    11009416    A/G/T   0.12/0.83/0.04  97  G   1.0 5   A/G/T   0.07/0.89/0.02  39
ch00    11009421    A/G 0.17/0.82   97  G   1.0 5   A/G 0.10/0.89   39
ch00    11009427    A/C/T   0.02/0.96/0.00  101 C   1.0 4   A/C 0.02/0.97   37
ch01    11009436    C/T 0.99/0.00   103 C   1.0 4   C   1.0 44
ch01    11009437    G/T 0.00/0.99   104 T   1.0 4   T   1.0 44
ch02    11009441    A/G 0.07/0.92   101 G   1.0 5   A/G 0.06/0.93   45
ch02    11009445    G   1.0 96  G   1.0 5   G   1.0 44

文件根据第 1 列和第 2 列进行排序,并且它们之间的行数相等。其中大约有 150 个文件,总大小为 6.5 GB

【问题讨论】:

  • 你尝试过类似join -j 2 -o 1.1,1.2,1.2,1.4,1.5,2.3,2.4,2.5 file file1的方法吗?
  • @revo 不会只加入第二个字段,而忽略第一个字段吗? (例如,ch00 11009427 和 ch01 11009427 的两条线不会连接在一起吗?)
  • @revo 我做到了,但这会在第 2 列中加入具有相同索引的所有行组合,因此:如果您有 ch00 11009427 和 ch01 11009427 它们将在结果中出现两次作为每个行组合。更何况这不是很实用的解决方案,如果你想加入 150 个文件...

标签: bash awk merge


【解决方案1】:

awk 可以实现你想要的。

awk -v OFS='\t' 'BEGIN{PROCINFO["sorted_in"]="@ind_str_asc"} {for(i=3;i<=NF;i++) a[$1 OFS $2]=a[$1 OFS $2] OFS $i}END{for(i in a)print i,a[i]}'

简要说明,

  • OFS='\t':设置输出字段分隔符为\t
  • PROCINFO["sorted_in"]="@ind_str_asc":按索引按升序排列数组,与字符串相比。更多详情请参考here。
  • for(i=3;i&lt;=NF;i++) a[$1 OFS $2]=a[$1 OFS $2] OFS $i:将值保存到数组中的特定索引中。
  • END{for(i in a)print i,a[i]}:打印数组中的索引及其对应的值。

【讨论】:

  • 对小文件来说就像一个魅力,但我有 150 个文件,每个文件大约 1M 行,它似乎在保存到文件之前将所有内容加载到内存中......
  • 实际上,它在具有 16 GB RAM 的台式电脑上处理 150 个文件和大约 7 GB 数据时运行良好!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-23
  • 2021-11-21
  • 2014-12-31
  • 2015-03-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多