値がx回以上発生する列を選択してください。

値がx回以上発生する列を選択してください。

複数の行と列を持つファイルがあります。数字2がx回以上表示される列を選択したいと思います。

私のタブで区切られたファイルは次のとおりです。

Individuals  M1 M2 M3
Ind1          0 0  2
Ind2          0 2  2
Ind3          2 2  2

この漫画の例では、数字2が複数回出現する列が欲しいとします。私の結果は次のとおりです

Individuals   M2 M3
Ind1          0  2
Ind2          2  2
Ind3          2  2

Rでは簡単ですが、ファイルが大きすぎるので時間がかかりますのでawkなどを利用してやりたいです。これを達成する方法を教えてもらえますか?

答え1

BEGIN { OFS = FS = "\t" }

FNR == NR {
        for (i = 2; i <= NF; ++i)
                if ($i == 2) ++c[i]
        next
}

{
        a[nf=1] = $1
        for (i = 2; i <= NF; ++i)
                if (c[i] >= t) a[++nf] = $i

        $0 = ""
        for (i = 1; i <= nf; ++i)
                $i = a[i]

        print
}

プログラムawkは各列でその値の発生回数を計算し2、それらの数を配列c(データの各列に1つの要素)に格納します。入力ファイル(ブロック)を初めて読み込むときにこれを行いますFNR == NR

入力ファイルを2番目に読み取る場合は、この数を使用して入力の適切な列を各行ごとaに読み取った配列に転送します。変数値は、t列を含めるかどうかを決定するしきい値として使用されます。これはfor最後のコードブロックの最初のループです。

次に、この配列から新しいデータレコードを作成して印刷します。

awkテストしてみてください(入力ファイルが2回渡されるようにコマンドラインに2回提供されることに注意してください)。

$ cat file
Individuals     M1      M2      M3
Ind1    0       0       2
Ind2    0       2       2
Ind3    2       2       2
$ awk -v t=1 -f script.awk file file
Individuals     M1      M2      M3
Ind1    0       0       2
Ind2    0       2       2
Ind3    2       2       2
$ awk -v t=2 -f script.awk file file
Individuals     M2      M3
Ind1    0       2
Ind2    2       2
Ind3    2       2
$ awk -v t=3 -f script.awk file file
Individuals     M3
Ind1    2
Ind2    2
Ind3    2
$ awk -v t=4 -f script.awk file file
Individuals
Ind1
Ind2
Ind3

答え2

これが速いかどうかはわかりません。

awk -v value=0 '
NR==FNR{for(i=2;i<=NF;i++){if($i==value){s[i]++}}}
NR!=FNR {
  printf "%s"OFS,$1
  for (i=2;i<=NF;i++){if(s[i]>1)last=i}
  for (i=2;i<=NF;i++){
    if(s[i]>1){
      if (i==last)printf "%s\n",$i
      else printf "%s"OFS,$i}
  }
}
' file file

OFSタブ(BEGIN{OFS="\t"}.)に設定することもできます。

関連情報