サブゼミ Computationnal Technique
Java 課題2(度数分布表の作成(1))
母集団$U(0,1)$から大きさ10の無作為標本を抽出して標本平均を計算することを400回繰り返す。
この400個の標本平均の度数分布表を作成せよ。
ただし,階級の幅$h$は以下に示すScottの算式で求めよ。
$$h = 3.5 s n^{-1/3}$$
$s$は,400個の標本平均の標本標準偏差,$n=400$である。
まずは,標本抽出と階級の幅の計算までは示すので,度数のカウントをやってみよう。
方針
クラス名をhistとし,主たる変数を次のように定義する。
- N
- 1回の標本抽出における標本の大きさ。int型。
- K
- 標本抽出回数。int型。
- x
- 標本抽出のたびに計算する標本平均を保存する大きさKの配列。double[]型。
- h
- 階級の幅。double型。
- nclass
- 階級数。int型。
- freq
- 各階級の度数を保存する大きさnclassの配列。int[]型。
ソースコード
このプログラムのポイントは,階級の幅$h$で区切られた区間に入る度数のカウントだ。
いま,ある階級の下限を$l$とすると,$x$の$K$個の要素のそれぞれについて
$$l \le x_i < l+h$$
が成立つかどうかをチェックして,成立つ場合にはその階級の度数を1だけ増加させる。
int[] freq = int int[nclass];
double l = x[0];
上のコードのポイントは,データ$x$が昇順にソートされていることだ。
さらに,jsという補助変数を使って,すでに何番目のデータまでチェックしたかをカウントしていることだ。
ゆえに,各階級に属するかどうかのチェックは,常に1番目のデータから始めるのではなく,
js番目のデータから始めることによって,$x_i$が上限未満であるかどうかを確認すればよい。
そして,上限以上の場合には,次の階級の下限($l+h$)と探索開始ポイントjsを設定して,
break分でループを抜ければよい。
int js = 0;
for (int i = 0; i < nclass; i++) {
for (int j = js; j < K; j++) {
if (x[j] < l + h) freq[i] += 1;
else {
l += h;
js = j;
break;
}
}
}
import java.util.Random;
import java.util.Arrays;
public class hist {
public static void main(String[] args) {
final int N = 10; //標本の大きさ
final int K = 400; //標本抽出回数
double[] x = new double[K]; //標本平均
//大きさNの無作為標本を抽出して標本平均を計算することをK回繰り返す
for (int k=0; k < K; k++) x[k] = Mean(Sample(N));
// データをソートする
Arrays.sort(x);
//階級の幅と階級数を計算する
double h = Hsize(x);
int nclass = Nclass(x, h);
System.out.printf("h=%10.5f¥n", h);
System.out.printf("nclass=%5d¥n", nclass);
//各階級の度数をカウントする
int[] freq = int int[nclass];
double l = x[0];
int js = 0;
for (int i = 0; i < nclass; i++) {
for (int j = js; j < K; j++) {
if (x[j] < l + h) freq[i] += 1;
else {
l += h;
js = j;
break;
} // end of else
} // end of j loop
} // end of i loop
} // end of main
} // end of class
上のコードでは以下のメソッドを使っている。 下に示すメソッドのコードをクラスhistの中に配置すれば完了である。
メドソッド名 | 計算内容 | Input | Output |
---|---|---|---|
Sample | 母集団$U(0,1)$から大きさnの標本を抽出する。 | 標本の大きさn(int型)。 | 大きさnの標本(double[]型)。 |
Mean | 大きさnの標本に関する標本平均を計算する。 | 大きさnの標本(double[]型)。 | 標本平均(double型)。 |
Var | 大きさnの標本に関する標本分散を計算する。 | 大きさnの標本(double[]型)。 | 標本分散(double型)。 |
Sd | 大きさnの標本に関する標本標準偏差を計算する。 | 大きさnの標本(double[]型)。 | 標本標準偏差(double型)。 |
Hsize | 階級の幅を計算する。 | 大きさnの標本(double[]型)。 | 階級の幅(double型)。 |
Nclass | 階級数を計算する。 | 大きさnの標本(double[]型)。 | 階級数(int型)。 |
メソッド
Sample: 母集団$U(0,1)$から大きさ$n$の標本を抽出する
public static double[] Sample(int n) {
double[] data = new double[n];
Random r = new Random();
for(int i=0; i < n; i++) data[i] = r.nextDouble();
return(data);
}
Mean: 標本平均を計算する
public static double Mean(double[] data) {
double mean = 0.0;
for (inti=0; i < data.length; i++) mean += data[i];
mean = mean / (double)data.length;
return(mean);
}
Var: 標本分散を計算する
public static double Var(double data[]) {
double mean = Mean(data);
doublevar = 0.0;
for (int i=0; i < data.length; i++) var += Math.pow(data[i]-mean, 2.0);
var = var / (double)(data.length-1);
return(var);
}
Sd: 標本標準偏差を計算する
public static double Sd(double[] data) {
double sd = Math.sqrt(Var(data));
return(sd);
}
Hsize: 階級の幅を計算する
public static double Hsize(double[] data) {
// Scottの方法
double h = 3.5*Sd(data)*Math.pow((double)data.length, -1.0/3.0);
return(h);
}
Nclass: 階級数を計算する
public static int Nclass(double[] data, double h) {
// dataは降順にソートされていること
int nclass = (int)Math.ceil((data[data.length-1]-data[0])/h);
return(nclass);
}