中央値を求めてみよう

中央値を求める方法をPerlプログラムを用いて説明します。

配列の中央値を求めてみよう

以下のような配列を考えてみます。

my @array1 = (1, 4, 5, 7, 8);
my @array2 = (1, 4, 6, 8, 9, 12);

配列の中央値を求めるサンプルプログラム

実際に配列から中央値を求めます。Statistics::Liteモジュールにmedian関数がありますが、この例では利用しません。

中央値は要素数が奇数の場合は要素の中央にある値となり、偶数の場合は中央にある2つの値の平均を中央値として求めることができます。

※コードの簡略化のため、ソート済みのデータを使用します。

use strict;
use warnings;

my @array1 = (1, 4, 5, 7, 8); 
my @array2 = (1, 4, 6, 8, 9, 12); 
my $median = 0;

sub get_median {
    my ($array_ref) = @_;
    my $array_cnt = @$array_ref;
    my $ret_median = 0;

    my $median_pos = int($array_cnt / 2);
    if ( $array_cnt % 2 == 1) {
        $ret_median = @$array_ref[$median_pos];
    } else {
        my $median_pos2 = $median_pos - 1;
        $ret_median = (@$array_ref[$median_pos] + @$array_ref[$median_pos2]) / 2;
    }
	return $ret_median;
}

$median = get_median(\@array1);
print "array1の中央値は:" . "$median" . "\n";

$median = get_median(\@array2);
print "array2の中央値は:" . "$median" . "\n";

実行結果

array1の中央値は:5
array2の中央値は:7

最大値、最小値などのように値の比較を行う必要がなく、要素の配列の中央の要素を取得できます。

表形式のデータから、特定の列の中央値を求めてみよう。

以下のデータを考えてみましょう。

nameage
bob9
alice11
tom13

配列,ハッシュのリファレンスで表すと以下のようになります。

$array_ref1 = [
  {name => 'bob',  age => 9},
  {name => 'alice',age => 11},
  {name => 'tom',  age => 13}
];

age列の中央値を求めるサンプルプログラム

参照するデータが複雑になったためデータアクセスも少し難しくなりましたが、

チェックする方法は先ほどと同じです。

※偶数パターンも入れるため$array_ref2も追加しています。

use strict;
use warnings;
use Data::Dumper;

my $array_ref1 = [
  {name => 'bob', age => 9},
  {name => 'alice',age => 11},
  {name => 'tom', age => 13}
];

my $array_ref2 = [
  {name => 'bob', age => 9},
  {name => 'alice',age => 11},
  {name => 'tom', age => 13},
  {name => 'carol', age => 15}
];

my $median = 0;

sub get_median {
    my ($array_ref) = @_;
    my $array_cnt = @$array_ref;
    my $median_pos = int($array_cnt / 2);
    my $ret_median = 0;

    if ( $array_cnt % 2 == 1) {
	    $ret_median = $array_ref->[$median_pos]->{'age'};
    } else {
        my $median_pos2 = $median_pos - 1;
        my $value1 = $array_ref->[$median_pos]->{'age'};
        my $value2 = $array_ref->[$median_pos2]->{'age'};
       
        $ret_median = ($value1 + $value2) / 2;
    }
    return $ret_median;
}

$median = get_median(\@$array_ref1);
print "array_ref1の中央値は:" . "$median" . "\n";

$median = get_median(\@$array_ref2);
print "array_ref2の中央値は:" . "$median" . "\n";

実行結果

array_ref1の中央値は:11
array_ref2の中央値は:12

リファレンスを扱った以外は先ほどと同じ処理になります。

このプログラムは、コピー&ペーストして、PerlBanjoで、すぐに試すことができます。

関連情報