파일에 대한 몇 가지 기본 통계를 수행하도록 bash 스크립트를 개선합니다.

파일에 대한 몇 가지 기본 통계를 수행하도록 bash 스크립트를 개선합니다.

다음과 같은 파일이 있습니다.

  • 파일 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길이 때문에 이것을 명시적인 프로그램 파일로 작성했습니다. 이는 주로 분석 결과를 인쇄하는 기능 때문입니다.

awkGNU 블록이 있는 경우 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모르는 경우 몇 가지 해결 방법이 필요합니다. 기본적으로 파일 속성을 임시 변수에 저장하고 새 파일의 시작 부분(이전 파일의 경우) 또는 마지막 파일의 블록에 통계를 인쇄합니다. 처리됨.ENDFILEEND

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

관련 정보