awkの数値形式と丸めの問題

awkの数値形式と丸めの問題

値列の平均を求めようとすると、正確な数値を取得したいと思います。

たとえば、次は入力値の列です。

1426044
1425486
1439480
1423677
1383676
1360088
1390745
1435123
1422970
1394461
1325896
1251248
1206005
1217057
1168298
1153022
1199310
1250162
1247917
1206836

次のコマンドを使用する場合:

... | awk '{ sum+=$1} END { print sum/NR}'

私は次のような結果を得ます1.31638e+06。しかし、私はこの形式の正確な数が欲しいです。1316375.05または、より良い結果を得る。 1,316,375.05

コマンドラインツールのみを使用してこれを行うにはどうすればよいですか?

編集1

最大値、最小値、平均値を取得するために、次の1行のawkコマンドを見つけました。

awk 'NR == 1 { max=$1; min=$1; sum=0 } { if ($1>max) max=$1; if ($1<min) min=$1; sum+=$1;} END {printf "Min: %d\tMax: %d\tAverage: %.2f\n", min, max, sum/NR}'

NRを1に初期化する必要があるのはなぜですか?を削除すると、NR == 1誤った結果が表示されます。

編集2

次のawkスクリプトが見つかりました。単一のコマンドで数値リストの最小値、最大値、中央値、平均を取得する方法はありますか?。数値データの単一列の合計、数、平均、中央値、最大値、最小値を一度に取得します。標準入力から読み込み、タブ区切りの出力列を1行に印刷します。少し修正しました。上記のawkコマンドと異なる必要はないことがわかりましたNR == 1(最初の編集で)。誰かが理由を説明できますか?これは、数値データがソートされて配列に格納されるという事実に関連していると思います。

#!/bin/sh

sort -n | awk '

  $1 ~ /^(\-)?[0-9]*(\.[0-9]*)?$/ {
    a[c++] = $1;
    sum += $1;
  }
  END {
    ave = sum / c;
    if( (c % 2) == 1 ) {
      median = a[ int(c/2) ];
    } else {
      median = ( a[c/2] + a[c/2-1] ) / 2;
    }

    {printf "Sum: %d\tCount: %d\tAverage: %.2f\tMedian: %d\tMin: %d\tMax: %d\n", sum, c, ave, median, a[0], a[c-1]}
  }
'

ベストアンサー1

... | awk '{ sum+=$1} END { print sum/NR}'

デフォルトでは、(GNU)awkは最大6桁の有効数字(指数を含む)を印刷します。これはデフォルト値に由来します。OFMT変数。ドキュメントにはあまり記載されていませんが、これは整数値ではなく数値にのみ機能します。

OFMTすべてのprint文に影響を与えるように変更するか、printfここで使用できるため、平均が整数の場合に機能します。%.3f小数点以下の3桁の数字を印刷するのと似ています。

...| awk '{ sum+=$1} END { printf "%.3f\n", sum/NR }'

fsumの意味gと精度修飾子(.prec2番目のリンク)のドキュメントを参照してください。

awk 'NR == 1 { max=$1; min=$1; sum=0 } ...'

初期化されませんNR。代わりに、それがNR1に等しいかどうか、つまり私たちが最初の行にあることを確認します。 (==比較です。=割り当てです。)そうであれば、maxおよびminを初期化しますsum。それがなければ、最初から始めるmaxでしょうmin。負の最大値または正の最小値を持つことはできません。

おすすめ記事