「0」と最初の2つのフィールドを除くcsvファイルのすべてのテキストを1に変換するには?

「0」と最初の2つのフィールドを除くcsvファイルのすべてのテキストを1に変換するには?

いくつかの大きな .csv ファイルがあり、このファイルをバイナリ (1 と 0) 形式に変換したいと思います。最初の2つのフィールドを除いて、テキストを含むすべてのセルは1になり、0は0のままです。

head Test.csv
Iss1,1,0,0,Hsapiens-I34,0,0,0,Mmusculus-H01,0,0
Iss1,11,0,Scerevisiae-U09,Hsapiens-I05,0,0,0,0,0,0
Iss1,21,0,0,Hsapiens-I05,0,0,0,Hsapiens-I31,0,0
Iss1,31,0,0,Mmusculus-H13,0,0,0,0,0,Hsapiens-I31
Iss1,41,0,Scerevisiae-U09,0,0,0,0,0,0,Hsapiens-I21
Iss1,51,0,0,0,0,0,0,Scerevisiae-U25,0,Hsapiens-I21
Iss1,61,0,0,Hsapiens-I34,0,0,0,Mmusculus-H13,0,0

予想される結果は

head Test.csv
Iss1,1,0,0,1,0,0,0,1,0,0
Iss1,11,0,1,1,0,0,0,0,0,0
Iss1,21,0,0,1,0,0,0,1,0,0
Iss1,31,0,0,1,0,0,0,0,0,1
Iss1,41,0,1,0,0,0,0,0,0,1
Iss1,51,0,0,0,0,0,0,1,0,1
Iss1,61,0,0,1,0,0,0,1,0,0

ここで、ファイル内のすべてのテキストは1に変換されます。

誰もがこの問題を克服する方法についてアドバイスをすることができれば非常に感謝します。

ありがとう

答え1

一緒にawkできること:

awk 'BEGIN {FS=OFS=","} {for (i=3;i<=NF;i++) {$i==0?1:$i=1}} 1' test.csv
  • BEGIN {FS=OFS=","}- 入力と出力の区切り文字をコンマに設定します。
  • for (i=3;i<=NF;i++)- 最大フィールド数に達するまでフィールド3を繰り返します。NF
  • $i==0?1:$i=1- フィールドが()iの場合は0何もせず1、そうでない場合はフィールドをi次に設定します。1
  • 1-1をtrueと解釈awkし、デフォルトでレコードを印刷します。

@EdMortonのコメントで提案したように、$1=($i!=0)isを使用する方が短い選択肢です。$i==0?1:$i=1

  • $i!=0iフィールドが次の場合は論理テストです。いいえ 0。それに応じてフィールド値をawk返し、上書きします。1true0false

答え2

パールの使用:

$ perl -F, -lne 'my @out = map { /^0$/ ? 0 : 1 } splice @F,2;
                 unshift @out, @F;
                 print join(",",@out)' Test.csv 
Iss1,1,0,0,1,0,0,0,1,0,0
Iss1,11,0,1,1,0,0,0,0,0,0
Iss1,21,0,0,1,0,0,0,1,0,0
Iss1,31,0,0,1,0,0,0,0,0,1
Iss1,41,0,1,0,0,0,0,0,0,1
Iss1,51,0,0,0,0,0,0,1,0,1
Iss1,61,0,0,1,0,0,0,1,0,0
Zed227,28897871,0,0,1,0,0,0,1,0,0
Zed227,28897881,0,1,1,0,0,0,0,0,0
Zed227,28897891,0,0,1,0,0,0,1,0,0
Zed227,28897901,0,0,0,0,0,0,0,0,1
lad1,1,0,1,0,0,0,0,0,0,1
lad1,11,0,1,0,0,0,0,1,0,0
lad1,21,0,0,1,0,0,0,0,0,0

仕組み:

Perlコマンドラインオプション:

  • この-F,オプションは、Perlにカンマをフィールド区切り文字として使用するように指示します。 -Fまた、フィールドを含む各入力行を名前付き配列に自動的に分割します@F。これは、awkがフィールドを$ 1、$ 2、$ 3などに自動的に分割するのと似ています。
  • -l入力から改行を削除して出力に再追加するなど、行末を自動的に処理するようにPerlに指示しますprint
  • -nPerlを次のように実行させますsed -n。つまり、各行を読み取って処理しますが、明示的に指示されたものだけを印刷します。
  • -ePerlに、次の引数が実行するスクリプトであることを伝えます。

スクリプト:

  • Perlはsplice()配列の一部を削除してその部分を呼び出し元に返すので、配列splice @F,2の最初の2つの要素を除くすべての要素を削除して返します@F。実際にspliceはそれより多くのことができますが、ここではここまでしか使いません。perldoc -f splice詳細より。

  • Perlのmap関数は、配列(リスト)の各要素に式を適用します。この場合、リストはsplice関数から返された要素です。mapここで使用される式は、要素が正規表現と一致する場合は1を返し、一致しない場合は1を返します。配列変数に割り当てられた配列を返します。詳細より。0/^0$/map@outperldoc -f map

    ただし、正規表現の代わりに三項eq演算子(たとえば)を使用して文字列同等比較を使用できます。$_ eq "0" ? 0 : 1文字列比較はこの単純な正規表現よりも高速ですが、.csvファイルが非常に大きくない限り(数千行)それほど大きくはありません。それでもeq使用する方が良いと思います/^0$/

    数値比較(==、 ie $_ == 0 ? 0 : 1)は、数字で始まらない文字列(前のスペースを無視)はゼロと評価されますが、これを1に置き換える必要があるため、必要な操作は実行されません。

  • unshift逆に、shift配列の先頭に要素を追加します。この場合、配列の残りの部分@F(つまり、削除されていない最初の2つの要素)を配列の先頭にsplice追加します@out。望むよりperldoc -f unshift

  • 最後に、@out配列はコンマで連結されて印刷されます。使用されるjoin機能の詳細についてはを参照してくださいperldoc -f join


これは単一の声明に縮小することができます。

perl -F, -lne 'print join ",", @F[0..1], map { /^0$/ ? 0 : 1 } splice @F,2' Test.csv

@out一時変数として必要ではなく、必須ではありませんunshift

まったく同じように動作しますが、理解するのは難しいです。特にPerlに慣れていない人にとっては、もっとそうです。各機能がどの入力を受け取るかを知るために、後ろから前に読む必要があります。

答え3

使用幸せ(以前のPerl_6)

~$ raku -ne 'my @a = .split(",");   \
             @a[2..*] = do for @a[2..*] { $_ ~~ 0.Int ?? 0 !! 1 };  \
             @a.join(",").put ;'   file

または:

~$ raku -ne 'my @a = .split(",");   \
             @a[2..*] .= map: { $_ ~~ 0.Int ?? 0 !! 1 };   \
             @a.join(",").put ;'   file

または:

~$ raku -ne 'my @a = .split(",");   \
             @a[2..*] .= map: { +( $_ !~~ 0.Int ) };   \
             @a.join(",").put;'   file

RakuはPerlプログラミング言語シリーズのプログラミング言語です。並行性、非同期、並列性(CAP)の高度なサポートが組み込まれています。

上記の最初の2つのコード例は、@casが投稿した優れたPerlの答えと非常によく似ています。 Rakuには、Rakuメソッドの構文砂糖である非対称の~~「スマートマッチング」演算子があることに注目する価値があります(.ACCEPTS()言い換えれば、「RHSはLHSを収容していますか?」)。~~Rakuの「スマートマッチング」演算子を使用すると、「タイプ」に関連する多くの問題を解決できます。

Rakuはまた、組み込みの三項演算子のための新しいフォーマットを提供しています:(テスト)?? 本物 !! 間違った。一部の人々は、この三項演算子が読みやすいと思います。または、3番目の例では、~~比較後に戻り変数が設定されるという事実を使用して、結果True/値をFalse/に渡したり強制したりできます。+(…)(…).Int01

[上記のコード例では、RHSは.Int実際に冗長であり、スマートマッチングは追加の強制なしでうまく機能します。ただし、デフォルトで解決されない特定の比較が必要な場合は、LHS / RHSキャスト(.Str、、.Intなどを介して)を実行できます。.Bool

入力例:

Iss1,1,0,0,Hsapiens-I34,0,0,0,Mmusculus-H01,0,0
Iss1,11,0,Scerevisiae-U09,Hsapiens-I05,0,0,0,0,0,0
Iss1,21,0,0,Hsapiens-I05,0,0,0,Hsapiens-I31,0,0
Iss1,31,0,0,Mmusculus-H13,0,0,0,0,0,Hsapiens-I31
Iss1,41,0,Scerevisiae-U09,0,0,0,0,0,0,Hsapiens-I21
Iss1,51,0,0,0,0,0,0,Scerevisiae-U25,0,Hsapiens-I21
Iss1,61,0,0,Hsapiens-I34,0,0,0,Mmusculus-H13,0,0

出力例:

Iss1,1,0,0,1,0,0,0,1,0,0
Iss1,11,0,1,1,0,0,0,0,0,0
Iss1,21,0,0,1,0,0,0,1,0,0
Iss1,31,0,0,1,0,0,0,0,0,1
Iss1,41,0,1,0,0,0,0,0,0,1
Iss1,51,0,0,0,0,0,0,1,0,1
Iss1,61,0,0,1,0,0,0,1,0,0

注:上記のコードはスペース値、、、00および0x0すべて0に-0変換します。特に、空の値の場合、すべての列が違いを検出するためのパラメータの有無にかかわらず、コードで埋められていることを確認する必要があります。 Perlファンの場合は、Rakuのドキュメントセクションを参照してください。0.00raku -ne '.split(",", :skip-empty).elems.say;':skip-empty「0」は真


000x0空白の値、、、および-0別の方法で処理するには、0.0Perlの回答を確認してください。 @StéphaneChazelasのPerl回答には、これらの値(およびスペース)を処理する方法の説明が含まれています。私の手で@casのPerlの答えは空の値、、、およびallを変更しました(空の値は@StéphaneChazelasのPerlの答えとは異なる方法で処理されます)00。したがって、あなたには選択肢があります(2つの言語、3つの治療法)!0x0-00.01


https://docs.raku.org/言語/operators#infix_??_!
https://docs.raku.org/routine/ACCEPTS
https://docs.raku.org/routine/~~
https://raku.org

答え4

別のperl方法は、@F次のように修正することです。

$ perl -F, -le 'map {$_ &&= 1} @F[2..$#F]; print join ",", @F' test.csv
Iss1,1,0,0,1,0,0,0,1,0,0
Iss1,11,0,1,1,0,0,0,0,0,0
Iss1,21,0,0,1,0,0,0,1,0,0
Iss1,31,0,0,1,0,0,0,0,0,1
Iss1,41,0,1,0,0,0,0,0,0,1
Iss1,51,0,0,0,0,0,0,1,0,1
Iss1,61,0,0,1,0,0,0,1,0,0

要素が1次のように処理される場合本物つまり、空の0文字列でも空の文字列でもない場合です。 、または同じゼロの他の表現は、次のよう00に処理されます。0x0-0 0.0zero本物に変更されました1

関連情報