慶應義塾大学 商学部・商学研究科

新保一成 研究室

開発と環境の経済分析...

サブゼミ 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
K
x
h
nclass
freq

ソースコード

このプログラムのポイントは,階級の幅$h$で区切られた区間に入る度数のカウントだ。 いま,ある階級の下限を$l$とすると,$x$の$K$個の要素のそれぞれについて $$l \le x_i < l+h$$ が成立つかどうかをチェックして,成立つ場合にはその階級の度数を1だけ増加させる。 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;
    }
  }
}
上のコードのポイントは,データ$x$が昇順にソートされていることだ。 さらに,jsという補助変数を使って,すでに何番目のデータまでチェックしたかをカウントしていることだ。 ゆえに,各階級に属するかどうかのチェックは,常に1番目のデータから始めるのではなく, js番目のデータから始めることによって,$x_i$が上限未満であるかどうかを確認すればよい。 そして,上限以上の場合には,次の階級の下限($l+h$)と探索開始ポイントjsを設定して, 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の中に配置すれば完了である。

メドソッド名計算内容InputOutput
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);
}