3

巨大なテキスト ファイル (サイズが 19GB) があります。これは、変数と観測値を含む遺伝子データ ファイルです。
最初の行には変数名が含まれており、次のように構成されています。

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 を新しい ID に置き換えます
  3. 元のファイルから最初の行を削除し、新しい行に置き換えます

これは良いアプローチですか、それともより良いアプローチがありますか?
これを達成するのに最適な言語はどれですか?
Python、vbscipt、Perl の経験を持つスタッフがいます。

4

3 に答える 3

4

置換行の長さが元のものと同じである限り、またはでパディングすることで同じにすることができる限り、「置換」全体がほとんどすべての言語で可能です(PythonとPerlについては確信しています) 。空白 (そうしないと、ファイル全体を書き直す必要があります)。

読み取りおよび書き込み用にファイルを開きます (w+モード)、最初の行を読み取り、新しい行を準備seekし、ファイルの位置 0 に移動し、新しい行を書き込み、ファイルを閉じます。

于 2013-01-24T19:18:54.167 に答える
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;
于 2013-01-24T19:34:35.450 に答える
1

これはかなり簡単なはずです。私は Python ファンなので、Python を使用します。概要:

  • マッピング ファイルを読み取り、マッピングを保存します (Python では辞書を使用します)。

  • 一度に 1 行ずつデータ ファイルを読み取り、変数名を再マップして、編集した行を出力します。

ファイルをその場で編集することは本当にできません...うーん、すべての新しい変数名が常に古い名前とまったく同じ長さである場合は可能だと思います。しかし、プログラミングを容易にし、実行中の安全性を確保するために、常に新しい出力ファイルを作成してから元のファイルを削除するのが最善です。これは、これを実行する前に少なくとも 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)
于 2013-01-24T19:18:53.847 に答える