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]++;
. 이는 출력 필드 구분 기호(이 경우 탭)로 구분된 처음 세 필드를 OFS
2D 배열의 첫 번째 키로 사용합니다 a
. 두 번째 키는 마지막 필드( $NF
)이며 값에 1을 추가하기만 하면 됩니다. 따라서 a
배열은 가능한 각 마지막 필드에서 각 문자, 시작 위치 및 끝 위치를 찾은 횟수를 계산합니다.
완료되면 END{ }
블록에서 배열의 모든 키(문자, 시작 및 끝 위치)를 반복한 다음 문자, 시작 및 끝 위치(값) 와 함께 a
가능한 두 개의 마지막 필드를 각각 인쇄합니다. of ), 그 다음은 가능한 각 마지막 필드가 처음 세 필드( ) 와 함께 나타나는 횟수입니다 . 이러한 문자, 시작 및 끝 위치에 특정 마지막 필드가 표시되지 않으면 빈 필드 대신에 오류가 발생하도록 거기에 필요합니다 .type1
type2
i
0+a[i][type1],0+a[i][type2]
0+
0
답변3
TSV 인식 유틸리티 Miller( mlr
)를 사용하여 입력을 헤더 없는 TSV 파일로 읽고, 필요한 열만 선택하고( 사용 cut
), 열 9의 값을 ;
각 열 조합 1에 대해 구분된 목록으로 수집/축소합니다. 2와 3(사용)을 사용한 다음 나머지 각 레코드에 대해 수집된 합계 문자열 수를 계산합니다 nest
(표현식 사용). 9열의 축소된 값은 결국 제거됩니다(with).C_R
S_R
put
cut -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
배열에 저장됩니다. %hash
A를 선언하고 [Z=>]
Raku의 축소 메타 연산자를 사용하여 처음 세 열과 함께 push
키/값 쌍을 여기에 추가합니다..[0..2]
열쇠마지막 .[*-1]
열은값. 마지막 명령문에서는 문자열 value
s eq
와 C_R
s가 유효한지 확인합니다 . 각 부울 결과는 , med 및 out 열로 S_R
변환됩니다 .Int
sum
put
입력 예:
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"]