다음과 같은 파일이 있습니다.
- 파일 1
chrV 20924149 chrX 17718866 chrIV 17493793 chrII 15279345 chrI 15072423 chrIII 13783700 chrM 13794
- 파일_2
chrI 230218 chrII 813184 chrIII 316620 chrIV 1531933 chrIX 439888 chrM 85779 chrV 576874 chrVI 270161 chrVII 1090940 chrVIII 562643 chrX 745751 chrXI 666816 chrXII 1078177 chrXIII 924431 chrXIV 784333 chrXV 1091291 chrXVI 948066
2열의 평균값과 총값은 물론 파일의 최대값과 최소값도 가져와야 합니다. 나는 stackoverflow에서 몇 가지 아이디어를 얻어 이 추악한 bash 스크립트를 만들었습니다.
#!usr/bin/env bash
for VARIABLE in Data/*.sizes
do
echo $VARIABLE
echo 'Genome length:'
awk -F '\t' '{ sum += $2 } END { print sum }' $VARIABLE
echo 'Chr number:'
awk -F '\t' '{ NR $1 } END { print NR }' $VARIABLE
echo 'Chr mean length:'
awk -F '\t' '{ total += $2 } END { print total/NR }' $VARIABLE
echo 'Longest Chr:'
awk -v max=0 '{if($2>max){want=$1" "$2; max=$2}}END{print want}' $VARIABLE
echo 'Smallest Chr:'
awk 'NR == 1 || $2 < min {line = $1; min = $2}END{print line " " min}' $VARIABLE
echo " "
done
작동하지만 더 나은 아이디어가 있다면 더 일반적으로 만들 수 있는 방법이 있을 수 있습니다. 왜냐하면 때로는 유사한 파일에서 이 작업이 수행되기 때문입니다.
awk
나는 일반적으로 and 를 사용하지 않으므로 조언을 주시면 감사하겠습니다 bash
.
나는 이것을 인쇄했습니다 :
Data/file_1
Genome length:
100286070
Chr number:
7
Chr mean length:
1.43266e+07
Longest Chr:
chrV 20924149
Smallest Chr:
chrM 13794
답변1
다음 awk
스크립트는 이 작업을 수행합니다. awk
길이 때문에 이것을 명시적인 프로그램 파일로 작성했습니다. 이는 주로 분석 결과를 인쇄하는 기능 때문입니다.
awk
GNU 블록이 있는 경우 ENDFILE
:
프로그램 파일(우리는 이를 이라고 부릅니다 analyze_genome_g.awk
):
#!/usr/bin/gawk -f
# Begin of file, characterized by FNR, the per-file line-counter, being 1.
# Initialize statistics: set sum, min, and max to first chromosome length
# and name of longest/shortest ('long'/'short') to first chromosome name.
FNR==1{s=min=max=$2; short=long=$1}
# All other lines: Update sum, min, and max lengths
FNR>1{s=s+$2;if (min>$2) {min=$2; short=$1}; if (max<$2) {max=$2; long=$1}}
# End-of-file (GNU awk feature!): Print statistics
ENDFILE{
printf("%s\n",FILENAME);
printf("- Genome length : %d\n",s);
printf("- Nr. of chromosomes : %d\n",FNR);
printf("- Mean chomosome length : %.1f\n",s/FNR);
printf("- Shortest chromosome : %s (length=%d)\n",short,min);
printf("- Longest chromosome : %s (length=%d)\n",long,max);
printf("\n");
}
당신은 그것을 호출할 수 있습니다
gawk -f analyze_genome_g.awk file_1 file_2 ...
산출:
file_1
- Genome length : 100286070
- Nr. of chromosomes : 7
- Mean chomosome length : 14326581.4
- Shortest chromosome : chrM (length=13794)
- Longest chromosome : chrV (length=20924149)
file_2
- Genome length : 12157105
- Nr. of chromosomes : 17
- Mean chomosome length : 715123.8
- Shortest chromosome : chrM (length=85779)
- Longest chromosome : chrIV (length=1531933)
기타 awk
변형:
상황을 awk
모르는 경우 몇 가지 해결 방법이 필요합니다. 기본적으로 파일 속성을 임시 변수에 저장하고 새 파일의 시작 부분(이전 파일의 경우) 또는 마지막 파일의 블록에 통계를 인쇄합니다. 처리됨.ENDFILE
END
printstats()
이를 보다 편리하게 하기 위해 출력을 수행하는 함수를 정의합니다 .
프로그램 파일( analyze_genome.awk
):
#!/usr/bin/awk -f
function printstats()
{
printf("%s\n",last_fn);
printf("- Genome length : %d\n",s);
printf("- Nr. of chromosomes : %d\n",last_fnr);
printf("- Mean chomosome length : %.1f\n",s/last_fnr);
printf("- Shortest chromosome : %s (length=%d)\n",short,min);
printf("- Longest chromosome : %s (length=%d)\n",long,max);
printf("\n");
}
# Begin of file
# FNR==1 always works, but now we have to save file properties, too.
# If it is _not_ the first file (NR, the global line counter, is larger than
# FNR, the per-file line-counter), print statistics (of the previous file).
FNR==1{
if (NR>1) printstats();
s=min=max=$2; short=long=$1;
last_fn=FILENAME; last_fnr=1;
}
FNR>1{
s=s+$2; if (min>$2) {min=$2; short=$1}; if (max<$2) {max=$2; long=$1};
last_fnr++;
}
END{printstats()}
비슷하게 부르시면 됩니다
awk -f analyze_genome.awk file_1 file_2 ...
일반적인 참고사항으로, 쉘 루프를 사용하여 텍스트 파일을 처리하는 것은효율성이 매우 낮기 때문에 권장되지 않습니다.; awk
등은 거의 모든 텍스트 처리 작업과 많은 통계 계산을 더 빠르게 수행할 수 있습니다.
답변2
GNU 버전의 데스크톱 계산기를 사용하여 yaml 형식으로 통계 보고서를 생성할 수 있습니다. 다음은 DC 코드의 주석이 많이 달린 버전입니다.
#!/usr/bin/env bash
for VARIABLE in Data/*.sizes
do
printf '%s:\n' "$VARIABLE"
< "$VARIABLE" awk '{$1="["$1"]";sub(/^-/,"_",$2)}1' \
| dc -e "
[32adnn]si # two-spaces indent in reporting
[
lix[Genome length:] n32an lsp
lix[Chr number:] n32an lkp
lix[Chr mean length:] n32an /1.0*p
lix[Longest Chr:] n32an lM n32an lmp
lix[Smallest Chr:] n32an lN n32an lnp
q
]sR
[dsmrdsMr]s+
[dsnrdsNr]s-
[
?z0=R # report stats @ eof
lk1+sk # increment line kounter
dls+ss # update running sum
dlm<+ # update max
dln>- # update min
cz0=? # call myself recursively to read next line
]s?
[
? # read the first line
1skdss # initialize knt, sum
dsmrdsM # initialize max
sNsn # initialize min
cl?x # read next line
]sI
lIx # set the ball rolling, kinda like main()
"
결과:
Data/file_1.sizes:
Genome length: 100286070
Chr number: 7
Chr mean length: 14326581.0
Longest Chr: chrV 20924149
Smallest Chr: chrM 13794
Data/file_2.sizes:
Genome length: 12157105
Chr number: 17
Chr mean length: 715123.0
Longest Chr: chrIV 1531933
Smallest Chr: chrM 85779
답변3
awk 'BEGIN{sum=0}{sum=sum+$2}END{print sum/finalcountofline}' filename ====Mean
awk 'BEGIN{sum=0}($2 > sum){sum=$2}END{print sum}' filename ===Max
awk 'NR==1{sum=$2}($2 < sum){sum=$2}END{print sum}' filename ===min