서로 다른 열의 연속 셀이 동일한 경우 쉘 스크립트를 사용하여 열의 단어 수를 계산하는 방법!

서로 다른 열의 연속 셀이 동일한 경우 쉘 스크립트를 사용하여 열의 단어 수를 계산하는 방법!

2열, 3열, 1열의 연속 셀이 동일한 경우 9열의 C_R합계 수를 계산하려고 합니다. S_R파일은 침대 형식(탭으로 구분된 형식)입니다. 원본 파일은 크고 첫 번째 열은 염색체 번호를 정의합니다. 파일의 처음 몇 줄은 다음과 같습니다.

chr1    10200   10300   8   10000   10214   100 214 S_R
chr1    10200   10300   8   10009   10233   100 224 S_R
chr1    10200   10300   8   10014   10220   100 206 S_R
chr1    10200   10300   8   10045   10215   100 170 S_R
chr1    10200   10300   8   10068   10209   100 141 S_R
chr1    10200   10300   8   10074   10300   100 226 C_R
chr1    10200   10300   8   10182   10283   100 101 S_R
chr1    10200   10300   8   10182   10387   100 205 C_R
chr1    10300   10400   4   10182   10387   100 205 S_R
chr1    10300   10400   4   10331   10467   100 136 S_R
chr1    10300   10400   4   10346   10461   100 115 S_R
chr1    10300   10400   4   10352   10468   100 116 S_R
chr1    10400   10500   3   10331   10467   100 136 S_R
chr1    10400   10500   3   10346   10461   100 115 S_R
chr1    10400   10500   3   10352   10468   100 116 S_R
chr1    11000   11100   2   11024   11163   100 139 S_R
chr1    11000   11100   2   11024   11188   100 164 S_R
chr1    11100   11200   3   11024   11163   100 139 S_R
chr1    11100   11200   3   11024   11188   100 164 S_R
chr1    11100   11200   3   11127   11296   100 169 S_R
chr1    11200   11300   1   11127   11296   100 169 S_R
chr1    11400   11500   2   11412   11561   100 149 S_R
chr1    11400   11500   2   11457   11608   100 151 S_R
chr1    11500   11600   3   11412   11561   100 149 S_R
chr1    11500   11600   3   11457   11608   100 151 C_R
chr1    11500   11600   3   11574   11744   100 170 S_R
chr1    11600   11700   3   11457   11608   100 151 S_R
chr1    11600   11700   3   11574   11744   100 170 C_R
chr1    11600   11700   3   11640   11815   100 175 S_R
chr1    11700   11800   4   11574   11744   100 170 S_R
chr1    11700   11800   4   11640   11815   100 175 C_R
chr1    11700   11800   4   11784   11963   100 179 S_R
chr1    11700   11800   4   11791   11936   100 145 S_R

위 표의 처음 8개 행에서 열 1, 2, 3이 동일하므로 임시 출력 파일은 다음과 같습니다.

chr1    10200   10300   2   6
chr1    10300   10400   0   4
chr1    10400   10500   0   3
chr1    11000   11100   0   2
chr1    11100   11200   0   3
chr1    11200   11300   0   1
chr1    11400   11500   0   2
chr1    11500   11600   1   2
chr1    11600   11700   1   2
chr1    11700   11800   1   3

출력 파일에서 열 4 C_R와 5는 다음과 같습니다.S_R

답변1

awk이는 다음을 통해 수행할 수 있습니다.

awk 'function report() {
       if (n) print last_key, 0+count["C_R"], 0+count["S_R"]
     }
     {key = $1 OFS $2 OFS $3}
     key != last_key {report(); n = 0; split("", count); last_key = key}
     {count[$9]++; n++}
     END {report()}' <your-file

-F '\t' -v OFS='\t'입력 필드가 탭으로 구분된 경우 입력 및 출력 파일 구분 기호를 추가하여 지정해야 할 수도 있습니다 . 기본적 FS으로 입력 필드 구분 기호 ( 에 의해 설정됨 -F)는 특별한 의미를 갖는 공백 문자입니다. 필드를 구분하는 공백 시퀀스와 선행 및 후행 공백이 삭제되거나 IOW 필드가 공백이 아닌 문자의 시퀀스입니다. 따라서 빈 필드가 있을 수 없으며 OFS공백이기도 합니다. 이는 단순히 출력의 필드가 공백으로 구분된다는 의미입니다.

답변2

이는 GNU ( awk대부분의 Linux 시스템의 gawk기본값 ) 방법입니다. awk여기서는 열이 탭으로 구분되어 있다고 가정하지만 이는 bed 파일이나 bedpe 파일처럼 보이기 때문에 둘 다 탭이 필요하므로 이것이 맞다고 합리적으로 확신합니다.

$ gawk -F'\t' -v OFS='\t' -v type1="C_R" -v type2="S_R" '
  { 
    a[$1 OFS $2 OFS $3][$NF]++; 
  } 
  END{ 
    for (i in a){  
      print i,0+a[i][type1],0+a[i][type2]
    }
}' file.bed 
chr1    11200   11300   0   1
chr1    11700   11800   1   3
chr1    10300   10400   0   4
chr1    11000   11100   0   2
chr1    10400   10500   0   3
chr1    11500   11600   1   2
chr1    11400   11500   0   2
chr1    11100   11200   0   3
chr1    11600   11700   1   2
chr1    10200   10300   2   6

설명하다

-F'\t'입력 필드 구분 기호를 탭으로 설정하고 -v OFS='\t'출력 필드 구분 기호를 탭으로 설정합니다. 다음으로 스크립트에서 사용할 type1두 개의 다른 변수를 설정합니다 .type2

스크립트의 본문은 바로 a[$1 OFS $2 OFS $3][$NF]++;. 이는 출력 필드 구분 기호(이 경우 탭)로 구분된 처음 세 필드를 OFS2D 배열의 첫 번째 키로 사용합니다 a. 두 번째 키는 마지막 필드( $NF)이며 값에 1을 추가하기만 하면 됩니다. 따라서 a배열은 가능한 각 마지막 필드에서 각 문자, 시작 위치 및 끝 위치를 찾은 횟수를 계산합니다.

완료되면 END{ }블록에서 배열의 모든 키(문자, 시작 및 끝 위치)를 반복한 다음 문자, 시작 및 끝 위치(값) 와 함께 a가능한 두 개의 마지막 필드를 각각 인쇄합니다. of ), 그 다음은 가능한 각 마지막 필드가 처음 세 필드( ) 와 함께 나타나는 횟수입니다 . 이러한 문자, 시작 및 끝 위치에 특정 마지막 필드가 표시되지 않으면 빈 필드 대신에 오류가 발생하도록 거기에 필요합니다 .type1type2i0+a[i][type1],0+a[i][type2]0+0

답변3

TSV 인식 유틸리티 Miller( mlr)를 사용하여 입력을 헤더 없는 TSV 파일로 읽고, 필요한 열만 선택하고( 사용 cut), 열 9의 값을 ;각 열 조합 1에 대해 구분된 목록으로 수집/축소합니다. 2와 3(사용)을 사용한 다음 나머지 각 레코드에 대해 수집된 합계 문자열 수를 계산합니다 nest(표현식 사용). 9열의 축소된 값은 결국 제거됩니다(with).C_RS_Rputcut -x

mlr --from=file --tsv -N \
    cut -f 1,2,3,9 then \
    nest --ivar ';' -f 9 then \
    put '
        a = splita($9,";");
        for (k in ["C_R","S_R"]) {
            $[k] = count(select(a, func(e) { return e == k }))
        }' then \
    cut -x -f 9

질문의 데이터가 주어지면 다음과 같은 탭으로 구분된 출력이 생성됩니다.

chr1    10200   10300   2       6
chr1    10300   10400   0       4
chr1    10400   10500   0       3
chr1    11000   11100   0       2
chr1    11100   11200   0       3
chr1    11200   11300   0       1
chr1    11400   11500   0       2
chr1    11500   11600   1       2
chr1    11600   11700   1       2
chr1    11700   11800   1       3

답변4

사용행복하다(이전 Perl_6)

~$ raku -e 'my @a = lines.map: *.split(/\s+/);  \
            my %hash.push:  [Z=>] @a.map(*.[0..2]), @a.map(*.[*-1]);  \
            put join "\t", .key, (.value.map: * eq "C_R")>>.Int.sum,  \
                (.value.map: * eq "S_R")>>.Int.sum  for %hash.sort;'  file

이것은 Perl 프로그래밍 언어 중 하나인 Raku로 작성된 답변입니다. lines빈칸에는 위의 내용이 map삽입 되어 있습니다. split결과는 @a배열에 저장됩니다. %hashA를 선언하고 [Z=>] Raku의 축소 메타 연산자를 사용하여 처음 세 열과 함께 push키/값 쌍을 여기에 추가합니다..[0..2]열쇠마지막 .[*-1]열은. 마지막 명령문에서는 문자열 values eqC_Rs가 유효한지 확인합니다 . 각 부울 결과는 , med 및 out 열로 S_R변환됩니다 .Intsumput

입력 예:

chr1    10200   10300   8   10000   10214   100 214 S_R
chr1    10200   10300   8   10009   10233   100 224 S_R
chr1    10200   10300   8   10014   10220   100 206 S_R
chr1    10200   10300   8   10045   10215   100 170 S_R
chr1    10200   10300   8   10068   10209   100 141 S_R
chr1    10200   10300   8   10074   10300   100 226 C_R
chr1    10200   10300   8   10182   10283   100 101 S_R
chr1    10200   10300   8   10182   10387   100 205 C_R
chr1    10300   10400   4   10182   10387   100 205 S_R
chr1    10300   10400   4   10331   10467   100 136 S_R
chr1    10300   10400   4   10346   10461   100 115 S_R
chr1    10300   10400   4   10352   10468   100 116 S_R
chr1    10400   10500   3   10331   10467   100 136 S_R
chr1    10400   10500   3   10346   10461   100 115 S_R
chr1    10400   10500   3   10352   10468   100 116 S_R
chr1    11000   11100   2   11024   11163   100 139 S_R
chr1    11000   11100   2   11024   11188   100 164 S_R
chr1    11100   11200   3   11024   11163   100 139 S_R
chr1    11100   11200   3   11024   11188   100 164 S_R
chr1    11100   11200   3   11127   11296   100 169 S_R
chr1    11200   11300   1   11127   11296   100 169 S_R
chr1    11400   11500   2   11412   11561   100 149 S_R
chr1    11400   11500   2   11457   11608   100 151 S_R
chr1    11500   11600   3   11412   11561   100 149 S_R
chr1    11500   11600   3   11457   11608   100 151 C_R
chr1    11500   11600   3   11574   11744   100 170 S_R
chr1    11600   11700   3   11457   11608   100 151 S_R
chr1    11600   11700   3   11574   11744   100 170 C_R
chr1    11600   11700   3   11640   11815   100 175 S_R
chr1    11700   11800   4   11574   11744   100 170 S_R
chr1    11700   11800   4   11640   11815   100 175 C_R
chr1    11700   11800   4   11784   11963   100 179 S_R
chr1    11700   11800   4   11791   11936   100 145 S_R

예제 출력:

chr1 10200 10300    2   6
chr1 10300 10400    0   4
chr1 10400 10500    0   3
chr1 11000 11100    0   2
chr1 11100 11200    0   3
chr1 11200 11300    0   1
chr1 11400 11500    0   2
chr1 11500 11600    1   2
chr1 11600 11700    1   2
chr1 11700 11800    1   3

put모든 열을 탭으로 구분하려면 [마지막 문에서 .key]로 바꾸세요..key.split(" ").join("\t")


중간 단계를 살펴보면 매우 이해하기 쉬운 경우가 많으므로 다음은 마이닝의 .raku마지막 2개 열 sum이전에 데이터()에 대한 Raku의 내부 표현 입니다.

~$ raku -e 'my @a = lines.map: *.split(/\s+/); my %hash.push:  [Z=>] @a.map(*.[0..2]), @a.map(*.[*-1]); .raku.say for %hash.sort;'  file
"chr1 10200 10300" => $["S_R", "S_R", "S_R", "S_R", "S_R", "C_R", "S_R", "C_R"]
"chr1 10300 10400" => $["S_R", "S_R", "S_R", "S_R"]
"chr1 10400 10500" => $["S_R", "S_R", "S_R"]
"chr1 11000 11100" => $["S_R", "S_R"]
"chr1 11100 11200" => $["S_R", "S_R", "S_R"]
"chr1 11200 11300" => "S_R"
"chr1 11400 11500" => $["S_R", "S_R"]
"chr1 11500 11600" => $["S_R", "C_R", "S_R"]
"chr1 11600 11700" => $["S_R", "C_R", "S_R"]
"chr1 11700 11800" => $["S_R", "C_R", "S_R", "S_R"]

https://docs.raku.org/언어/hashmap
https://raku.org

관련 정보