列の各部分の中央値を計算する方法を学びます。

列の各部分の中央値を計算する方法を学びます。

次のデータがあります。

111 5
111 6
111 1
222 8
222 9
222 1
222 3
555 9
555 7
555 6

の各値について$1可能であれば、AWKを使用して$2その値のすべての値の中央値を取得したいと思います。$1

希望の出力:

111 5 5
111 6 5
111 1 5
222 8 5.5
222 9 5.5
222 1 5.5
222 3 5.5
555 9 7
555 7 7
555 6 7

$1ここで、5は5、6、1(==値)の中央値111、5.5は8、9、1、3の中央値です。

ベストアンサー1

すべてのUNIXシステム上のすべてのシェルでsort + awkを使用してください。

$ cat tst.awk
$1 != prev { if (NR>1) prt(); prev=$1 }
{ vals[++cnt] = $2 }
END { prt() }

function prt(   i,med) {
    med = (vals[int((cnt+1)/2)] + vals[int((cnt/2)+1)]) / 2
    for (i=1; i<=cnt; i++) {
        print prev, vals[i], med
    }
    cnt = 0
}

$ sort -k1,1n -k2,2n file | awk -f tst.awk
111 1 5
111 5 5
111 6 5
222 1 5.5
222 3 5.5
222 8 5.5
222 9 5.5
555 6 7
555 7 7
555 9 7

$2上記のコードは、すべての現在の値を名前付き配列$1に保存し、値が変更されたかファイルの終わりに達したときに呼び出してその配列の中央値を計算し、名前付き変数に保存してループに印刷します。 sとのすべての関連追加。vals[]$1prt()med$1$2med

出力行は上記で並べ替えられました。これが問題の場合は、最初に行を飾って元の順序を維持し、上でsort + awkを実行してから元の順序で並べ替え、最後に装飾を取り消すことができます。

GNU awkがあり、キー値がすでにソートされている場合は、関数asort()内で呼び出すことができるので、以前にprt()呼び出す必要はありません。ソートがない場合は、すべてを配列に保存してからEND部分でソートできます。しかし、図に示すように、最初に呼び出すのが最も明確でシンプルで効率的で、移植性に優れています。sortawksort

おすすめ記事