"0"과 처음 두 필드를 제외한 csv 파일의 모든 텍스트를 1로 변환하는 방법은 무엇입니까?

"0"과 처음 두 필드를 제외한 csv 파일의 모든 텍스트를 1로 변환하는 방법은 무엇입니까?

여러 개의 큰 .csv 파일이 있는데 이 파일을 이진(1과 0) 형식으로 변환하고 싶습니다. 처음 두 필드를 제외하고 텍스트가 포함된 모든 셀은 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배열의 처음 두 요소를 제외한 모든 요소를 ​​삭제하고 반환합니다 @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)는 숫자로 시작하지 않는 문자열(앞 공백 무시)은 0으로 평가되는 반면, 이를 1로 바꿔야 하기 때문에 필요한 작업을 수행하지 않습니다.

  • unshift이와 반대로 shift배열의 시작 부분에 요소를 추가합니다. 이 경우 배열의 나머지 내용 @F(즉, 제거되지 않은 처음 두 요소 )을 배열의 시작 부분에 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)에 대한 고급 지원이 내장되어 있습니다.

위의 처음 두 코드 예제는 @cas가 게시한 뛰어난 Perl 답변과 매우 유사합니다. Raku 에는 Raku 메소드의 구문 설탕 ~~인 비대칭 "스마트 매칭" 연산자가 있다는 점은 주목할 가치가 있습니다 (.ACCEPTS()즉, "RHS가 LHS를 수용하는가?"). ~~Raku의 "스마트 매칭" 연산자를 사용하면 "유형"과 관련된 많은 문제를 해결할 수 있습니다 .

Raku는 또한 내장된 삼항 연산자에 대한 새로운 형식을 제공합니다: (시험)?? 진짜 !! 잘못된. 어떤 사람들은 이 삼항 연산자가 읽기 쉽다고 생각합니다. 또는 세 번째 예에서는 ~~비교 후에 반환 변수가 설정된다는 사실을 사용하여 결과 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변환 합니다 . 특히 빈(null) 값의 경우 모든 열이 차이를 감지하기 위한 매개변수 유무 에 관계없이 코드로 채워져 있는지 확인해야 합니다 . Perl 팬이라면 Raku 문서 섹션을 참조하세요.0.00raku -ne '.split(",", :skip-empty).elems.say;':skip-empty"0"은 참이다.


000x0공백 값 ​​, , -0및 다르게 처리하려면 0.0Perl 답변을 확인하세요. @StéphaneChazelas의 Perl 답변에는 이러한 값(및 공백)을 처리하는 방법에 대한 설명이 포함되어 있습니다. 내 손에 @cas의 Perl 답변은 빈 값, 00, 0x0및 all을 -0변경 했습니다 (빈 값은 @StéphaneChazelas의 Perl 답변과 다르게 처리됩니다). 따라서 귀하에게는 선택권이 있습니다(2개 언어, 3개 치료법)!0.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문자열도 빈 문자열도 아닌 경우입니다. , 또는 같은 0의 다른 표현은 다음 00과 같이 처리됩니다.0x0-0 0.0zero진짜로 변경되었습니다 1.

관련 정보