複数の行と列を持つファイルがあります。数字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"}
.)に設定することもできます。