2013-01-24 50 views
3

我有一个巨大的文本文件(19GB的大小);它是一个包含变量和观测数据的遗传数据文件。
第一行包含变量名和跟随它们的构造:在巨大的txt制表符分隔文件的第一行替换文本

id1.var1 id1.var2 id1.var3 id2.var1 id2.var2 id2.var3 

我需要调换ID1,ID2等。与对应的是在另一个文本文件中的值(此文件具有约7K行)ID是不以任何特定的顺序,它的结构如下:

oldId newIds 
id1 rs004 
id2 rs135 

我做了一些谷歌搜索,真的无法找到语言这将允许执行以下操作:

  1. 读取的第一线
  2. 与新的ID代替IDS
  3. 从原始文件删除第一行,用新的
  4. 更换

这是一个好方法还是有更好的方法?
这是最好的语言来完成这个?
我们有在python,vbscipt和Perl方面有经验的人。

回答

1

这应该很容易。我会使用Python,因为我是一名Python粉丝。大纲:

  • 读取映射文件,并保存映射(在Python中,使用字典)。

  • 每次读取一行数据文件,重新映射变量名称并输出编辑过的行。

你真的无法编辑就地文件...嗯,我想你可以,如果每一个新的变量名总是一模一样的长度与旧名称。但为了便于编程和运行时的安全性,最好总是编写新的输出文件,然后删除原文。这意味着在运行此操作之前,您至少需要20 GB的可用磁盘空间,但这应该不成问题。

这是一个Python程序,显示如何做到这一点。我用你的示例数据来制作测试文件,这似乎工作。

#!/usr/bin/python 

import re 
import sys 

try: 
    fname_idmap, fname_in, fname_out = sys.argv[1:] 
except ValueError: 
    print("Usage: remap_ids <id_map_file> <input_file> <output_file>") 
    sys.exit(1) 

# pattern to match an ID, only as a complete word (do not match inside another id) 
# match start of line or whitespace, then match non-period until a period is seen 
pat_id = re.compile("(^|\s)([^.]+).") 

idmap = {} 

def remap_id(m): 
    before_word = m.group(1) 
    word = m.group(2) 
    if word in idmap: 
     return before_word + idmap[word] + "." 
    else: 
     return m.group(0) # return full matched string unchanged 

def replace_ids(line, idmap): 
    return re.sub(pat_id, remap_id, line) 

with open(fname_idmap, "r") as f: 
    next(f) # discard first line with column header: "oldId newIds" 
    for line in f: 
     key, value = line.split() 
     idmap[key] = value 

with open(fname_in, "r") as f_in, open(fname_out, "w") as f_out: 
    for line in f_in: 
     line = replace_ids(line, idmap) 
     f_out.write(line) 
+0

非常感谢你!我将把这段代码展示给我的程序员。谢谢 –

4

整个“替换”的事情是有可能在几乎任何语言(我敢肯定了Python和Perl),更换线路只要长度是一样的原始,或者如果它可以是使得与填充空格相同(否则,你将不得不重写整个文件)。

打开文件进行读取和写入(w+模式),读取第一行,准备新行seek,在文件中将位置写入0,写入新行,关闭文件。

+0

如果“id1”=>“rs004”,它可能不起作用。所以可能有写入新文件的唯一方法。 – alex

+0

谢谢。我现在正在运行一个Python代码,它符合您的建议。 ids的长度不一样,文件需要重写。我在Windows环境中,可能需要几小时才能运行。我希望它能起作用。 –

3

我建议你使用Tie::File模块,它将文本文件中的行映射到一个Perl数组,并将在头后的行重写一个简单的工作。

此程序演示。它首先将所有旧/新ID读入散列,然后使用Tie::File映射数据文件。文件的第一行(在$file[0]中)使用替换进行修改,然后解除阵列以重写并关闭文件。

您需要更改我用过的文件名。另外请注意,我假定ID始终是“单词”字符(字母数字加下划线),后面跟着一个点,并且没有空格。当然,在修改文件之前,您需要备份文件,并且在更新真实文件之前,应该在较小的文件上测试该程序。

use strict; 
use warnings; 

use Tie::File; 

my %ids; 
open my $fh, '<', 'newids.txt' or die $!; 
while (<$fh>) { 
    my ($old, $new) = split; 
    $ids{$old} = $new; 
} 

tie my @file, 'Tie::File', 'datafile.txt' or die $!; 
$file[0] =~ s<(\w+)(?=\.)><$ids{$1} // $1>eg; 
untie @file; 
相关问题