【问题标题】:Merge/join two big files合并/加入两个大文件
【发布时间】:2014-05-07 20:03:22
【问题描述】:

我想在第一列加入 2 个文件: 文件 1 包含 46395029 行,文件 2 包含 86510559。

file1.txt

>ID sequence
CJP75M1:393:C2T21ACXX:8:1101:2069:1997 1:N:0:_45    TAGTATTACGACG
CJP75M1:393:C2T21ACXX:8:1101:2711:1992 1:N:0:_65    TCCGAGGCCCTGTAATTGGAATGAGTAC
CJP75M1:393:C2T21ACXX:8:1101:3822:1989 1:N:0:_115   CCGGAGAGGGAGCCTGAGAAACGGCTACCAC

file2.txt

>ID      Barcode
CJP75M1:393:C2T21ACXX:8:1101:2069:1997 1:N:0:_45    CTCG
CJP75M1:393:C2T21ACXX:8:1101:2711:1992 1:N:0:_65        CTAG
CJP75M1:393:C2T21ACXX:8:1101:3822:1989 1:N:0:_115       CTGG

我想将这两个文件合并到第一个列上:

>TAGTATTACGACG    CTCG
TCCGAGGCCCTGTAATTGGAATGAGTAC     CTAG
CCGGAGAGGGAGCCTGAGAAACGGCTACCAC     CTGG

只需要 file1 中的行,因此结果文件应包含“仅”46395029 行。 我用 awk 做到了:

    awk 'BEGIN {FS= "\t"; OFS="\t"} { while (getline < "file1.txt") { f[$1] = $2} {print $2, f[$1] }}' "file2.txt" | sed '1d' > result.txt

但它真的很长(运行 2 天)。我有一个 64 位 / 16Go RAM 的 linux debian(稳定)服务器

有什么想法吗? 谢谢

【问题讨论】:

  • 文件中的“键”是否以某种方式排序?
  • 好奇,为什么是java标签和C标签?
  • 不,他们不是。事实上,在文件 2 中我有所有的 ID,而在文件 1 中这是一个子集
  • 因为我愿意接受任何语言的任何建议!

标签: java c join awk merge


【解决方案1】:

这是awk的另一种方式:

awk 'FNR==1{next}NR==FNR{map[$1,$2]=$3;next}(map[$1,$2]){print map[$1,$2],$3}' file2 file1
  • 跳过两个文件的第一行
  • 在 file2 的第 1 列和第 2 列创建一个索引数组
  • 如果文件 1 中存在映射,则打印该行

【讨论】:

    【解决方案2】:

    这是 Java (7+) 中的一个解决方案——你要求它:)

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.nio.charset.Charset;
    import java.nio.charset.StandardCharsets;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;
    
    import static java.nio.file.StandardOpenOption.*;
    
    public final class Job
    {
        private static final Pattern PATTERN
            = Pattern.compile("(\\S+\\s+\\S+)\\s+(.*)");
    
        public static void main(final String... args)
            throws IOException
        {
            final Map<String, String> fromFile1 = new HashMap<>();
    
            final Charset charset = StandardCharsets.US_ASCII;
            final Path file1 = Paths.get("/tmp/f1.txt");
            final Path file2 = Paths.get("/tmp/f2.txt");
            final Path dstfile = Paths.get("/tmp/dst.txt");
            Matcher m;
            String line, key, value;
            StringBuilder sb;
    
            // Lines from file 1
            try (
                final BufferedReader reader = Files.newBufferedReader(file1,
                    charset);
            ) {
                reader.readLine();
                while ((line = reader.readLine()) != null) {
                    m = PATTERN.matcher(line);
                    if (m.matches())
                        fromFile1.put(m.group(1), m.group(2));
                }
            }
    
            // Write in destination file
            try (
                final BufferedReader reader = Files.newBufferedReader(file2,
                    charset);
                final BufferedWriter writer = Files.newBufferedWriter(dstfile,
                    charset, CREATE, TRUNCATE_EXISTING);
            ) {
                reader.readLine();
                while ((line = reader.readLine()) != null) {
                    m = PATTERN.matcher(line);
                    if (!m.matches())
                        continue;
                    key = m.group(1);
                    value = fromFile1.get(key);
                    if (value == null)
                        continue;
                    sb = new StringBuilder(value).append('\t')
                        .append(m.group(2)).append('\n');
                    writer.write(sb.toString());
                }
                writer.flush();
            }
        }
    }
    

    将其放入名为 Job.java 的文件中。要编译,您需要 JDK 7+,并且:

    javac Job.java
    

    要执行,你需要相当多的内存,所以:

    java -Xmx4G Job
    

    当然要根据需要更改路径!


    请注意,如果您必须经常操作此类文件,我建议您尽可能将这些行设置为固定长度;治疗会更快。或者甚至可以使用数据库引擎?

    【讨论】:

    • 你刚刚用火箭筒杀死了一只小蚂蚁!该死!! :)
    • @jaypal meh,如果治疗需要几个小时,您可以花几分钟时间编写一些自定义代码 ;)
    • 我不能保证正确性,但这项工作值得一票。
    【解决方案3】:

    join 命令可能是您需要的:join 需要在连接字段上对输入文件进行排序

    join -o 1.3,2.3 -a 1 -e "??" <(sed 1d file1.txt | sort -k1,1) <(sed 1d file2.txt | sort -k1,1)
    

    根据您的样本数据产生的结果:

    CGGACGTGATCACTGTGACGCCTTGCGTGTTACGGTTGTT CNCG
    TAGTATTACGACG AGGC
    TCCGAGGCCCTGTAATTGGAATGAGTAC ??
    CCGGAGAGGGAGCCTGAGAAACGGCTACCAC ??join -o 1.3,2.3 -a 1 -e "??" <(sed 1d file1.txt | sort -k1,1) <(sed 1d file2.txt | sort -k1,1)
    TTGGAGGGC ??
    TTGATGGTAGTATC ??
    AATAAAACGATGCATTTATGTATTTTTGATT ??
    TCCTCGATAGTATAGTGGTTAGTATCCCCGCC ??
    TGATGGTAGTATC ??
    

    有了这么多数据,我认为最好的办法是将数据导入关系数据库(例如sqlite)并使用 SQL 生成报告。

    【讨论】:

    • 是的,我试了一下,它从2小时开始运行......我不知道它是否正常。我在 python 中使用 sqlite
    猜你喜欢
    • 2011-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-20
    • 1970-01-01
    相关资源
    最近更新 更多