統計クラスの作成(標準偏差、配列昇順)
統計計算クラスを作ってみる①
今回は行列計算クラスの作成に引き続き、統計計算クラスも自作してみようと思います。
最終的には、統計計算のデスクトップアプリなどを作成したいと思ってます。まだ構成などは決まっていませんが、成績処理などに使えるアプリを想定しています。
スマホアプリでもいいんですが、データの読み込みなどを考えるとPCでの操作がいいかと思います。
成績処理に必要なものといえば、「標準偏差」や「中央値」などのデータです。難しいことを考えるならば「○○分布」なども必要になると思いますが、今はまだこの辺は考慮しません。
ということで今回は、「標準偏差を求めるメソッド」と「中央値などを求めるために配列をソートするメソッド」を作成します。なお使用する言語はC#です。
標準偏差メソッドを作る
まずは、テストなどの採点を行ったときに必要となる標準偏差を求めるメソッドを自作していきます。
学生時代、試験の成績表をみると得点以外に、「偏差値」なども記載されて要ると思います。学生が一番気になる部分ですね!この「偏差値」を求めるためには標準偏差が必要となります。
標準偏差を求めるためには平均点が必要となります。なので最初に合計と平均を求めるメソッドを作成します。
合計や平均を求めるメソッドはシンプルなのでコードを載せるだけにします。
public static double Sum( double[] x ) { double sum = 0; for(int i=0;i<x.Length;i++) { sum += x[i]; } return sum; }
public static double Average( double[] x ) { return ( Sum( x ) / x.Length ); }これらを用いて分散と標準偏差メソッドを作成します。
標準偏差を求める方法は以下のようになります。
\begin{eqnarray} s &=& \sqrt{s^2} \\ &=&\sqrt{\displaystyle \frac{1}{n} \displaystyle \sum_{i=1}^n(x_i-\bar{x})^2} \end{eqnarray}
まずは分散から作成します。
先程示した数式の平方根の中が分散になります。
これをコードで表すと以下のようになります。
public static double Dispersion( double[] x ) { int n = x.Length; double ave = Average( x ); double z = 0; for(int i=0;i<x.Length;i++) { z += (x[i] - ave) * (x[i] - ave); } return z / n; }計算中に平均値を使うので、ループ文の開始前に予め先程作成していたAverageメソッドを利用します。
変数のnに関しては、使用せずにreturnのときにx.Lengthを使用してもいいと思います。
分散メソッドが作成できたら、最後に標準偏差メソッドを作成します。
先程の数式より、標準偏差は分散の平方根となります。
平方根にはMathクラスのSqrtメソッドを利用します。
コードは以下のようになります。
public static double StanderdDeviation( double[] x ) { return Math.Sqrt( Dispersion( x ) ); }Sqrtメソッドの引数に、分散メソッドを代入し計算します。
分散メソッドができればシンプルですね!
配列をソートするメソッド
次は中央値などを求めるために配列をソートするメソッドを作成します。
今回採用する方法はバブルソートです。
バブルソートとは、隣同士のデータを比較し、入れ替える作業を繰り返し行うソート方法です。すべてのデータがソートできた時点で処理は終了します。
この処理のコードを書いていきます。
まず、配列がソートできているかを判断するメソッドを作成します。
private static bool JudgeDescendingOrder( double[] x ) { bool b = true; for(int i=0;i<(x.Length-1);i++) { if(x[i] < x[i+1]) { b = false; break; } } return b; }隣同士のデータを比較し、大小関係が異なっている場合はboolをfalseに変更。breakを使い、ループ文から抜けます。このメソッドは1箇所でも異なる部分があれば、それ以降は比較する必要がないのでbreakを使い無駄な計算を省くことが可能です。
このメソッドを使い、データの入れ替えを繰り返します。よって以下のようにメソッドを作成します。
public static double[] AscendingOrder( double[] x ) { while( !JudgeAscendingOrder( x ) ) { for(int i=0;i<(x.Length-1);i++) { if( x[i] > x[i+1] ) { double z = x[i]; x[i] = x[i + 1]; x[i + 1] = z; } } } return x; }先程作成したJudgeAscendingOrderをwhile文の条件式に当てはめていますが、一箇所でも異なる場合falseが返ってきますので「!」を付け、否定しています。
while文の中では、配列のデータを左から順に比較していくのでfor文を利用します。for文の中で入れ替えを行う処理を記述しています。
今回は、引数の配列をそのまま入れ替えているので、呼び出し元の配列も入れ替わります。(クラス型の引数のため)
これに関しては、入力データの順番を意識する必要がないと判断したためです。もし、元の順番が必要になった場合は修正します。
まとめ
今回は「合計」「平均」「分散」「標準偏差」「配列を昇順で並び替える」メソッドを作成しました。
昇順で並び替えるメソッドは次回以降に「中央値」や「最頻値」を求める際に使います。最頻値に関して、データが昇順に並んでいる必要は無いですが、処理の仕方の都合により昇順に変更を行います。
また、今回書いたメソッドはすべてdouble型の配列を引数にとっていますが、実際には整数型の配列の可能性も存在するため、int用も作成しておきます。
すでに、次回用のメソッドも記述されていますが、Gitにコードを貼っておきます。こちら
今回はこの辺で、ではまた!