統計クラスの作成(中央値、最頻値、四分位数)
統計クラスを作ってみる②
前回に引き続き、統計計算のクラスを作成していきたいと思います。
今回は、前回作成した「昇順メソッド」を利用し、中央値と最頻値を求めるメソッドと四分位数を求めるメソッドの作成を行いたいと思います。
正直どちらも本当に必要かわかりませんが、統計クラスを名乗っているので実装したいと思います。
中央値
まずは、中央値を求めるメソッドから実装しましょう。
中央値とは、その名の通り「中央の値」です。データを昇順に並べ替え、左と右から個数を数えていき、真ん中にある値が中央値です。
この処理では、データの数が奇数か偶数かで方法が少し異なります。
- 奇数の場合
- 偶数の場合
奇数の場合はシンプルで、昇順に並べ替えたデータを真ん中の値は一つに定まります。
例えば、「1,2,3,4,5,6,7」のような7個のデータが存在するときは、中央値は「7」です。
偶数の場合は少し計算が増えます。データを昇順に並べ替え、真ん中の値を探すとデータは1つに定まりません。
そのため、データの個数が偶数のときには、真ん中の前後にあるデータの平均をとり、その結果が中央値となります。
例えば、「1,2,3,4,5,6,7,8」のような8個のデータが存在するするときは、真ん中の前後のデータは「4」と「5」になります。よって中央値は「4.5」となります。
public static double Median( double[] x ) { int n = x.Length; x = AscendingOrder( x ); if( n%2 == 0 ) { n = (n / 2) - 1; return ( x[n] + x[n+1] ) / 2; } else { n = (n - 1) / 2; return x[n]; } }まずは引数の配列データを昇順に並べ替えるために前回作成したAcsendingOrderを呼び出し並べ替えを行います。
次にデータの個数が奇数か偶数かで条件分岐させます。
偶数の場合は、データの個数より1小さい値を変数に格納します。これはデータの数と配列の添字が1ずれているためです。その後、先程格納した添字とその添字より1大きい添字の配列を合計し、半分にします。これが偶数のときの中央値となります。
奇数の場合は、データの個数より1小さい値を半分にし変数に格納します。これも配列の添字として使うためです。奇数の場合はその添字のデータが中央値となります。
最頻値
次は最頻値メソッドを作成します。
最頻値とは、データの集まりの中で最も多いデータの値のことです。例えば、「1,1,2,3,4,4,4,5,6」のようなデータが存在したときの最頻値は、3個存在する「4」となります。
なお、最頻値は複数存在する場合もあるため、今回実装するメソッドの戻り値は配列とします。
コードは以下の通りです。
public static double[] Mode( double[] x ) { Listかなり複雑なコードですね。list = new List (); x = AscendingOrder( x ); double number; int maxCount = 0; for(int i=0;i<x.Length;i++) { int count = 0; number = x[i]; for(int w=i;w<x.Length;w++) { if(number == x[w]) { count++; } else { break; } } if( count >= maxCount ) { if(count > maxCount) { list.Clear(); } list.Add( number ); maxCount = count; } } double[] mode = new double[list.Count]; int modeCount = 0; foreach( double n in list ) { mode[modeCount] = n; modeCount++; } return mode; }
まず処理の都合から前回作成した昇順に並べ替えるメソッド「AscendingOrder」を使用し、データをソートします。こうすることで同じ値のデータが並ぶため数えるときに楽になります。
処理の方法は、基準となる値を設定し、比較する値をループ文でずらしていく方法です。同じ値ならカウントを増やしていき、異なる場合はループから抜けます。
ループを抜けたときは最大カウントと比較し、以下のように処理を行います。
- 最大カウント未満
- 最大カウントと同じ
- 最大カウントより大きい
次の基準値を設定し、ループ処理を再開します。
最頻値を格納するリストに今回の値を追加します。
追加後、次の基準値を設定し、ループ処理を再開します。
今まで作成していたリストを初期化し、新しく今回の値を追加します。
このとき、最大カウントを更新しておきます。
更新後は、次の基準値を設定し、ループ処理を再開します。
四分位数
中央値を求めるメソッドを実装したので、応用して四分位数についても実装しようと思います。
四分位数とは、シンプルに言うと中央値の中央値です。ちなみに中央値は第2四分位数です。
例えば、「50,54,62,62,67,71,78,80,82,86,87」のようなデータが存在するとき、第2四分位数(中央値)は「71」。
中央値より前に存在するデータの中央値を求めます。これが第1四分位数で値は「62」となります。中央値より後ろに存在するデータの中央値が第3四分位数で値は「82」となります。
これをコードで書くと以下のようになります。
public static double FirstQuartile( double[] x ) { int n = x.Length; double[] y; if( n%2 == 0 ) { y = new double[x.Length/2]; } else { y = new double[(x.Length-1)/2]; } for (int i = 0; i<y.Length; i++) { y[i] = x[i]; } return Median( y ); }
public static double ThirdQuartile( double[] x ) { int n = x.Length; double[] y; if( n%2 == 0 ) { y = new double[x.Length/2]; } else { y = new double[(x.Length-1)/2]; } int m = x.Length - y.Length; int count = 0; for(int i=m;i<y.Length;i++) { y[count] = x[i]; count++; } return Median( y ); }引数のデータ数が偶数か奇数かで処理が変わりますが、基本は引数のデータ数の半分の長さので配列を作成しデータを格納します。
後は先程実装した中央値を求めるメソッドを使い求めます。
これにより箱ひげ図の作成も行うことができるようになりました。
まとめ
今回は、中央値と最頻値、四分位数を求めるメソッドを実装しました。
これで統計計算に必要となる基本的な計算処理は実装できたと思います。あとは○○分布などの実装ですかね?大学のときに少し統計学は勉強しましたが覚えていないので勉強するとところからスタートですね。
一旦、統計計算クラスの作成はここまでにして、次はデスクトップアプリケーションの作成に向けて、データの読み込み部分の実装やグラフの作成を中心に進めたいと思います。
作成したグラフは画像ファイルなどで保存できるようにしたと思っています。できるかはわかりませんが、、、
今回作成した分までGitにコードを貼っておきます。こちら
今回はこの辺で、ではまた!
コメント
コメントを投稿