Text-Processing

如何為具有重疊區域的間隔分配值?

  • April 4, 2019

我有兩個大文件,第一個文件包含一些 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

第二個文件包含一些超過 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”對值中的任何一個。

此外,對於這個“numberA”和“numberB”對值,其各自的“id”必須與 data.position 中的“id”匹配。如果這都是真的,那麼我想將 data.intervals 中的相應“id.uniq”插入到 data.posiitons 文件中相應行的列中。

這裡還有另一個問題:其中一些區間相互重疊,一個位置可能落在 2 個或超過 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 腳本完成此任務?

您可以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 and $ 數標量。
  • grep應選擇滿足數字在範圍內的約束的唯一 ID。否則"NA"通過。

引用自:https://unix.stackexchange.com/questions/510325