ファイルに関するいくつかの基本的な統計を実行するように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

関連情報