2つの大きなファイルがあり、最初のファイルには約85K行のスペースが含まれています。
head data.intervals
id id_uniq numberA numberB
1 g1 5 20
1 g2 6 29
1 g3 17 35
1 g4 37 46
1 g5 50 63
1 g6 70 95
1 g7 87 93
2 g8 3 15
2 g9 10 33
2 g10 60 77
2 g11 90 132
2番目のファイルには、200万行を超えるいくつかの場所が含まれています。
head data.posiitons
id number
1 4
1 19
1 36
1 49
1 90
2 1
2 20
2 89
2 93
2 120
私が望むのは、位置ファイルの「number」列の各値について、data.intervalsファイル内の「numberA」と「numberB」の値のペアの1つと同じかその間にあるかを検索することです。 。
さらに、「numberA」と「numberB」の値のペアの場合、対応する「id」はdata.positionの「id」と一致する必要があります。これがすべて真であれば、data.intervalsの対応する "id.uniq"をdata.posiitonsファイルの対応する行列に挿入したいと思います。
これには別の問題があります。これらの間隔の一部が互いに重なり合い、位置が2つ以上の間隔範囲に属する可能性があります。各間隔に個別に割り当てたいです。
これは私が得たい最終的な出力です(NAは場所がある間隔の範囲内にないことを意味します)。
id number assigned1
1 4 NA
1 19 g1,g2,g3
1 36 NA
1 49 NA
1 90 g6,g7
2 1 NA
2 20 g9
2 89 NA
2 93 g11
2 120 g11
BashまたはPerlスクリプトを使用してこれを行うことができるソリューションはありますか?
ベストアンサー1
Perl
次の方法を使用してこれを実行できます。
$ perl -lane '
my($id, $uniq_id, $lower, $upper) = @F;
$h{$id}{$uniq_id}{MIN} = $lower;
$h{$id}{$uniq_id}{MAX} = $upper;
push @{$order{$id}}, $uniq_id;
}{
while(<STDIN>) {
chomp;
my($id, $number) = split;
print join "\t", $id, $number,
join(",", grep { $h{$id}{$_}{MIN} < $number and $h{$id}{$_}{MAX} > $number } @{$order{$id}})
|| qw/NA/;;
}
' data.intervals < data.posiitons
出力:
1 4 NA
1 19 g1,g2,g3
1 36 NA
1 49 NA
1 90 g6,g7
2 1 NA
2 20 g9
2 89 NA
2 93 g11
2 120 g11
働く:
- まず、インターバルファイルを読み取り、ID、一意のIDでキーを指定し、範囲エンドポイントを含むハッシュデータ構造を構築します。
- ハッシュは、
%order
一意のIDが見つかった順序を保存することによって同じ順序で再生されます。 OTW、ハッシュ順はランダムです。 - 次に、場所ファイルを読み取り、各レコード(または行)を最初に解凍し、$ idおよび$numberスカラーに配置します。
grep
範囲内で数値制約を満たす一意のIDを選択する必要があります。それ以外の場合は a が"NA"
渡されます。