他のファイルの範囲に属する範囲に基づいてファイルから行を抽出する

他のファイルの範囲に属する範囲に基づいてファイルから行を抽出する

ca.というファイルがあります。 2列と3列(範囲の始まりと終わり)の値に基づいて17000行を抽出する必要があります。

File_1.txt

NC_018723.3 88839   102219
NC_018723.3 156206  160651
NC_018723.3 160885  165615
NC_018723.3 178410  191119
NC_018723.3 226179  242932
NC_018723.3 243929  310071
NC_018723.3 384020  413475

範囲を含む2番目のファイルがあります。

File_2.txt

8410001 8420000
8420001 8430000
28550001    28560000
28560001    28570000
111910001   111920000
111920001   111930000
209310001   209320000
209320001   209330000
209330001   209340000

2列と3列の範囲がfile_2.txtの範囲に属するfile_1.txtから行を抽出する方法を探しています。

どんなアイデアでも大いに感謝します。

ベストアンサー1

TXR不明瞭な音声解決策。

まず、file_1.txt実際に次の範囲に属するいくつかの範囲ケースが追加されましたfile_2.txt

NC_018723.3 88839   102219
NC_018723.3 156206  160651
NC_018723.3 160885  165615
NC_018723.3 178410  191119
NC_018723.3 226179  242932
NC_018723.3 243929  310071
NC_018723.3 384020  413475

FOO_1 8420001 8430000
FOO_2 8430000 8440000
FOO_3 8430000 8440000
FOO_4 209310001 209320001
FOO_5 209310001 209320000
FOO_6     209310002 209320000
FOO_7 209310002 209319999

ランニング:

$ txr soln.tl 
FOO_1 8420001 8430000
FOO_5 209310001 209320000
FOO_6 209310002 209320000
FOO_7 209310002 209319999

コードは次の場所にありますsoln.tl

(defvarl rtree [tree nil to])

(defun add-range (tree range)
  (tree-insert tree range))

(defun lookup-range (tree range)
  (let* ((iter (tree-begin tree (from range)))
         (node (tree-next iter))
         (found (if node (key node))))
    (if (and found
             (>= (from range) (from found))
             (<= (to range) (to found)))
      found)))

(awk
  (:inputs "file_2.txt")
  (t (fconv i i) (add-range rtree [f 0]..[f 1])))

(awk
  (:inputs "file_1.txt")
  (t (fconv - i i)
     (if (lookup-range rtree [f 1]..[f 2])
       (prn))))

ここでのアプローチは、バイナリ検索ツリーを使用して範囲を保存することですfile_2.txt

TXR Lispには範囲タイプがあります:アクセサfromto。 REPLでこれを閲覧できます。

1> 10..20
#R(10 20)
2> (typeof *1)
range
3> (from *1)
10
4> (to *1)
20

soln.tlプログラムでは、式は[tree nil to]新しいバイナリ検索ツリーを構成します。nil空にしておくことがto重要な機能です。to範囲フィールドにアクセスする関数であることに注意してください。このツリーに範囲オブジェクトを配置し、toそのオブジェクトのフィールドにキーを設定します。

関数がlookup-range最も複雑です。入力範囲が与えられると、その範囲がツリーに格納された範囲内に含まれるかどうかを決定します。tree-begin順番にツリーナビゲーションを開始しますが、入力範囲フィールドtoより低いキー(つまりフィールド)を持つすべてのノードを無視するために使用されます。fromつまり、検索範囲のフィールドtoよりも大きい最も低いフィールドを持つノードを探しています。from

ノードが見つかったら、単純なネストされたテストを適用してそれを確認します。

関数定義の後には2つの式があります(awk ..)。最初のawkプロセスはfile_2.txtツリーハッシュを埋めます。 Awkfconv演算子は、フィールドを整数に変換し、[f 0]..[f 1]そこから範囲オブジェクトを構築するために使用されます。

2番目の{awk ...)ジョブは、file_1.txt範囲検索と一致するレコード印刷を処理します。

バランスバイナリツリーは範囲に使用されるため、file_2.txtサイズが大きくなる可能性があります。

でフィールドを変更したため、スペースは出力に保存されませんfconv。 Awk では、フィールドに割り当てると、出力フィールド区切り文字を使用してフィールドを連結してレコードイメージを再計算します。

スペースを維持するために、awk2番目のスペースをこのように変更できます。ローカル変数を導入し、それを使用して記録されたrecsave値を保持します(クラシックAwkと同様)。rec$0

(awk
  (:inputs "file_1.txt")
  (:let recsave)
  (t (set recsave rec)
     (fconv - i i)
     (if (lookup-range rtree [f 1]..[f 2])
       (prn recsave))))

おすすめ記事