既存のテーブルの特定のパラメータに基づいて新しいテーブルを作成する

既存のテーブルの特定のパラメータに基づいて新しいテーブルを作成する

テーブルから複数の個別のCSVファイルを作成したいと思います。以下は例表です。

gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
gene1  1            0          0         0         0      0            0          0         0         0
gene2  1            1          1         1         0      0            0          0         0         0
gene3  0            1          0         0         1      0            0          0         0         0
gene4  1            0          0         0         0      1            0          0         0         0
gene5  0            0          0         0         0      1            0          1         0         0
gene6  1            0          0         0         0      0            0          0         1         1
gene7  0            1          0         0         0      0            0          0         0         1

CSV(または他のタブで区切られたファイル)を作成したいと思います。

  1. 「S1」を含む列ヘッダーの下に「1」を含むすべてのデータを抽出しますが、同じ遺伝子の場合、「S2」を含むすべてのヘッダーの値は「0」です。たとえば、

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene1  1            0          0         0         0      0            0          0         0         0
    gene2  1            1          1         1         0      0            0          0         0         0
    gene3  0            1          0         0         1      0            0          0         0         0
    
  2. REFファイル(S1またはS2)から値が「1」の行のみを取得しますが、他のすべてのフィールド(「REF」を含まない行ヘッダーなど)に対しては、「0」の行のみを取得します。たとえば、

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene1  1            0          0         0         0      0            0          0         0         0
    gene4  1            0          0         0         0      1            0          0         0         0
    
  3. ここで、REF_S1*には「1」が含まれます。みんなその他(すなわち、REFではない)S1サンプルは「0」+みんなREF_S2*は「0」+ですが、他のS2サンプル(REFではありません)は「1」です。たとえば、

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene6  1            0          0         0         0      0            0          0         1         1
    gene7  0            1          0         0         0      0            0          0         0         1
    
  4. 最後に、すべての*FLは「1」、すべての*ホストは「0」です。たとえば、

    gene   REF_S1_host  REF_S1_FL  S1_host1  S1_host2  S1_FL  REF_S2_host  REF_S2_FL  S2_host1  S2_host2  S2_FL
    gene3  0            1          0         0         1      0            0          0         0         0
    gene7  0            1          0         0         0      0            0          0         0         1
    

しかし、どうすればいいのかわかりません。どんな提案でも歓迎します。

答え1

私は仮定する

  • (多少)示されているように、データはスペースで区切られます。
  • テーブルには常に11個の列があります(ただし、行数に制限はないかもしれません)。
  • セル値にはスペースは含まれません。 (特に1行(タイトル)と1列(遺伝子)を除くすべての項目は0ORです1。)

にするのは簡単ですawk

  1. ...「S1」を含む列ヘッダーの下に「1」を含むすべてのデータがありますが、同じ遺伝子の場合、「S2」を含むすべてのヘッダーの値は「0」です。

    つまり、

      (2列は1 OR 3列は1 OR 4列は1 OR 5列は1 OR 6列は1)
        AND
       7列は0
        AND
       8列は0 AND 9列は0
        AND 10列は0 AND 11列は0




    だから、

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1 || $4==1 || $5==1 || $6==1)  &&
                    $7==0 && $8==0 && $9==0 && $10==0 && $11==0 { $1=$1; print }
        '
    
    • OFS「出力フィールドの区切り記号」。入力がタブ区切りまたはスペースで区切られている場合でも、データをカンマ区切りフィールドに書き込むように指示-v OFS=','します。awk
    • 最初の行(タイトル行)をスキップするように指示しますNR==1 { next }awkヘッダー行を印刷するにはに変更しますNR==1 { $1=$1; print; next }
    • 次の2行は、上記のAND / ORロジックをエンコードします。
    • { $1=$1; print }条件が満たされたら、ラインを印刷します。この  $1=$1メソッドは、最初のフィールドを自分と同じに設定します。何も起こらないように聞こえるかもしれません。実際には、awk新しい(カスタム)出力フィールド区切り文字(カンマで指定)を使用して行を強制的に書き換えることはトリックです。心が変わり、入力に示されているように行を正確に出力するには、  -v OFS=','およびを削除します$1=$1;
  2. ... REFファイル(S1またはS2)には「1」の値があり、他のすべてのフィールドには「0」の値のみを持つ行のみ...

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1 || $7==1 || $8==1)  &&
                    $4==0 && $5==0 && $6==0 && $9==0 && $10==0 && $11==0 { $1=$1; print }
        '
    
  3. ここで、REF_S1*には「1」が含まれており、他のすべて(つまり非REF)S1サンプルは「0」、すべてのREF_S2 *は「0」ですが、他のすべてのS2サンプル(非REF)は「1」です。

    awk -v OFS=',' '
            NR==1 { next }
            ($2==1 || $3==1) && $4==0 && $5==0 && $6==0  &&
                    $7==0 && $8==0 && ($9==1 || $10==1 || $11==1) { $1=$1; print }
        '
    
  4. ...すべての*FLは「1」で、すべての*ホストは「0」です。

    awk -v OFS=',' '
            NR==1 { next }
            ($3==1 || $6==1 || $8==1 || $11==1)  &&
                    $2==0 && $4==0 && $5==0 && $7==0 && $9==0 && $10==0 { $1=$1; print }
        '
    

答え2

この問題に対する解決策は、次を使用することです。真珠3つのステップに進んでください。

  • 選択基準正規表現が与えられたら、基準を満たすフィールド番号をエクスポートするサブルーチンを作成します。
  • 最初の行またはヘッダー行を読み取るときにサブルーチンを使用して、リストされた各条件のフィールドインデックスを生成します。
  • 最後に、これらのさまざまな配列の助けを借りて、List :: MoreUtilsモジュールから取得した関数を使用してブール選択基準を実行します。
  • 注:ワンホットモードでは、4つの状況が個別に実行されます。それ以外の場合、出力はインターリーブされます。
perl -MList::MoreUtils=any,all -lane '
  BEGIN {
    sub mkAry {
      my $re = shift;
      grep { $_ }
      map { $h{$_} }
      grep { /$re/ } keys %h
    }
  }
  if ($. == 1) {
    print;
    @h{@F} = (0..$#F);
    @S1 = mkAry qr/S1/;
    @S2 = mkAry qr/S2/;
    @REF = mkAry qr/REF/;
    @notREF = mkAry qr/^(?!.*REF)/;
    @REF_S1 = mkAry qr/REF_S1/;
    @REF_S2 = mkAry qr/REF_S2/;
    @notREF_S1 = mkAry qr/^(?!.*REF)(?=.*S1)/;
    @notREF_S2 = mkAry qr/^(?!.*REF)(?=.*S2)/;
    @FL = mkAry qr/FL/;
    @host = mkAry qr/host/;
    next;
  }

  ##_1_:
  print if
    any { $_ == 1 } @F[@S1] and
    all { $_ == 0 } @F[@S2]
  ;

  ##_2_:
  print if
    any { $_ == 1 } @F[@REF] and
    all { $_ == 0 } @F[@notREF]
  ;

  ##_3_:
  print if
    any { $_ == 1 } @F[@REF_S1] and
    all { $_ == 0 } @F[@notREF_S1] and
    all { $_ == 0 } @F[@REF_S2] and
    any { $_ == 1 } @F[@notREF_S2]
  ;

  ##_4_:
  print if
    any { $_ == 1 } @F[@FL] and
    all { $_ == 0 } @F[@host]
  ;
' file | column -t

関連情報