awkを使用してテーブルをフィルタリングする方法

awkを使用してテーブルをフィルタリングする方法

関心のある各列の特定の値に基づいて複数の列を持つテーブルをフィルタリングする方法を知りたいです。

ここにこの例があります。

    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16782   0       0       0       0
    Chr1    16783   0       0       0       0
    Chr1    16784   0       0       0       0
    Chr1    16785   0       0       0       0
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

3、4、5、6列から0を含むすべての行を削除したいです。

私はすでに試しました。

cat STARsamples_read_depth.txt | awk '$3 != 0 && $4 != 0&& $5 != 0 && $6 != 0' | less

ただし、4列すべてではなく、一部の列のみがゼロの行も削除します。

それを行う方法はありますか?

ありがとう

アサ

答え1

awkを使用すると、関心のあるフィールドをリンクすると、ゼロ以外の数値が生成されるかどうかをテストできます。

$ awk '($3$4$5$6)+0' file
    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

または、何らかの理由で各フィールドを個別にテストする場合は、次の手順を実行します。

$ awk '{for (i=3; i<=6; i++) if ($i != 0) { print; next } }' file
    Chr1    16644   0       0       1       1
    Chr1    16645   0       0       1       1
    Chr1    16646   0       0       1       1
    Chr1    16647   0       0       1       1
    Chr1    16648   0       0       1       1
    Chr1    16649   0       0       1       1
    Chr1    16650   0       0       1       1
    Chr1    16651   0       0       1       1
    Chr1    16786   0       0       1       1
    Chr1    16787   0       0       1       1
    Chr1    16788   0       0       1       1
    Chr1    16789   0       0       1       1
    Chr1    16790   0       0       1       1

質問に示すように、入力が整数でない可能性がある場合(コメントを参照)、上記の2番目のスクリプトを使用するか、接続の数値比較の代わりに文字列にすることができます。

awk '($3$4$5$6) != "0000"' file

答え2

コメントで@Devonが述べ||たように&&

その理由は、少なくとも次の行を表示したいからです。一つ3、4、5、6列の値は0とは異なります。

これは理解のもう一つの方法です。列がすべてゼロの行を削除しようとしています。反対の観点から始めましょう。印刷この列はすべてゼロの行です。これはとても簡単です。

awk '$3 == 0 && $4 == 0 && $5 == 0 && $6 == 0'

今あなたが欲しい上下反転このステートメントはすべての行を表示します。いいえ上記の条件を満たしてください。ですから、その言葉を否定すればいいのです。

awk '(!($3 == 0 && $4 == 0 && $5 == 0 && $6 == 0))'

しかし、上記のコマンドもあなたの要件を満たしています。

とにかく、論理否定ルール、命題の否定「ㅏそして第二」はい「AじゃないまたはBではない」。したがって、このステートメントを拒否するには、次のようにします。

$3 == 0 && $4 == 0 && $5 == 0 && $6 == 0

すべての式を否定し、すべて変換する必要があります。「そして」オペレーター「または」

$3 != 0 || $4 != 0 || $5 != 0 || $6 != 0

これで、コマンドが機能しない理由をよりよく理解できます。使用するステートメントの否定は次のとおりです。

$3 == 0 || $4 == 0 || $5 == 0 || $6 == 0

これは、少なくとも次のすべての行を削除することを意味します。一つ列(すべてではない)は0です。

答え3

使用awk:

$ awk '!/(\s+0){4}$/' file
Or
$ awk '!/([[:space:]]+0){4}$/' file

2番目のコマンドにはPOSIX awkが必要です。

すべてのフィールド(つまり$3、、、、$4および0)を含むレコードを削除します。 @EdMortonが提案したように$5$6

$ awk '{ x=4;for(i=3;i<=6;i++) if ($i==0) {x--;} }x' file

$3$4$5およびフィールドのいずれかが$6ゼロの場合、そのフィールドを含むレコードを削除します。

$ awk '{ x=1;for(i=3;i<=6;i++) if ($i==0) {x=0;break;} }x'

forループは、(i=3;i<=6;i++)フィールド3、4、5、6をフィルタリングするために発生します。

関連情報