Up

平均値の差のt検定:独立なサンプルの場合

 

2つの独立なサンプルの平均値の差の検定(t test)(岡本安晴「データ分析のための統計学入門」おうふう)を行うVisual C++/win32プログラムを作成した。なお、Win32コンソールアプリケーションの新規作成については<Win32コンソールアプリケーションの新規作成>で、C++の標準入出力(コンソール入出力)については<標準入出力cincout>で、C++におけるテキストファイル入出力については<テキストファイル入出力>で説明している。

 プログラムの実行例を図1に示す。

図1

 

入力ファイルはプログラム・ソースコード・ファイル*.cppと同じフォルダに用意する。

入力データファイル設定のソースコードは以下のようになっている。

 

              cout << "入力データファイル = " ;

              string ifnm;

              cin >> ifnm;

              ifstream fin( ifnm );

             

              if ( ! fin){                                                        //                          入力ファイルの設定が失敗するとfinfalseを返す。

                                          cout << "入力ファイルエラー" << endl;

                                          cout << "何か文字を入力して終了。" << endl;

                                          string s;

                                          cin >> s;

                                          return 9;

              }

 

入出力ストリーム・オブジェクトの変数finを条件式に用いると、ストリームに何かエラーがあるとfalseが返される。

 

入力ファイルは図2の形式で用意する。

図2

 

第1行に基準値を書く。第1グループのデータは基準値の書かれた行の次の行から書き、最後のデータの次の行に基準値より小さい値を書いて、データの区切りとする。次に第2グループのデータを書く。最後のデータの次に基準値より小さい値を書いて、データの終わりとする。finによる入力は空白あるいは改行で区切られた文字列単位に行われ、空白行は読み飛ばされる。図2では、空白行を入れて2つのグループのデータの区切りが判りやすくなるようにしている。

エディタでデータを新しく用意したときは、保存してからプログラムで読み込む。エディタの画面に打ち込んだだけでは、その内容はファイルに反映されない。

基準値を基に読み込むデータ数を数えているが、以下のコードによって行っている。

 

              double c;

              fin >> c;                             //            基準値の読み込み

 

              int nx = 0;                         //            Xのデータ数

              do{

                            double v;

                            fin >> v;

                            if (v < c) break;

                            nx++;

              }while(true);

              int ny = 0;                         //            Yのデータ数

              do{

                            double v;

                            fin >> v;

                            if (v < c) break;

                            ny++;

              }while(true);

              fin.close( );

 

データ数のカウント後、入力用ストリームを開きなおして、以下のようにデータの読み込みを行っている。

 

              fin.open( ifnm );

              double v;

              fin >> v;

              double * x;

              x = new double[nx];

              for (int i = 0; i < nx; i++){

                            fin >> x[i];

              }

              fin >> v;

              double * y;

              y = new double[ny];

              for (int i = 0; i < ny; i++){

                            fin >> y[i];

              }

              fin.close();

 

データの読み込み後、t検定のためのt値の計算が行われる。t値は以下のコードで求めている(岡本安晴「データ分析のための統計学入門」おうふう)。

 

              double SDDxy = ::sqrt( (nx * sqr(SDX) + ny * sqr(SDY)) * ((1.0/nx) + (1.0/ny)) / (nx + ny - 2.0) );

              double t = (MeanX - MeanY) / SDDxy;

 

計算を終えて結果の書き出しが終了すると「何か文字を入力して終了」と表示されるので、適当な文字キーを押してEnterキーを押すとプログラムの終了となる。この部分は以下のコードによって処理されている。

 

              cout << endl << "計算終了" << endl;

              cout << "何か文字を入力して終了" << endl;

              string ckstr;

              cin >>ckstr;

              return 0;

 

出力ファイルもファイル名を図1のように設定すると、プログラムソースコードファイル*.cppと同じフォルダ内に作成される。図2のデータでプログラムを実行したときの出力ファイルをVisualC++のエディタで開くと図3のようになっている。

図3

 

数値が小数点以下5桁で出力されているが、これは書式を設定するためのマニピュレータを以下のように使用して行っている。

 

              fout << setprecision(5) << fixed << endl;

 

setprecision( k ) << fixed」と出力すると小数点以下k桁の出力となる。

 

プログラムソースコード全体は以下の通りである。

==============================================

// t_test_ind.cpp : コンソール アプリケーションのエントリ ポイントを定義します。

//

 

#include "stdafx.h"

 

#include <iostream>                       //            cin, coutの使用のため

#include <fstream>                        //            ifstream, ifstreamの使用のため

#include <iomanip>                        //            setwなどの使用のため

#include <string>                           //            string型の使用のため

#include <sstream>                        //            文字列ストリーム使用のため

 

using namespace std;                     //            cin, coutなどが属する名前空間

 

double sqr( double v ){

                            return  v * v;

}

 

int _tmain(int argc, _TCHAR* argv[])

{

              cout << "入力データファイル = " ;

              string ifnm;

              cin >> ifnm;

              ifstream fin( ifnm );

             

              if ( ! fin){                                                        //            入力ファイルの設定が失敗するとfinfalseを返す。

                                          cout << "入力ファイルエラー" << endl;

                                          cout << "何か文字を入力して終了。" << endl;

                                          string s;

                                          cin >> s;

                                          return 9;

              }

 

              double c;

              fin >> c;                             //            基準値の読み込み

 

              int nx = 0;                         //            Xのデータ数

              do{

                            double v;

                            fin >> v;

                            if (v < c) break;

                            nx++;

              }while(true);

              int ny = 0;                         //            Yのデータ数

              do{

                            double v;

                            fin >> v;

                            if (v < c) break;

                            ny++;

              }while(true);

              fin.close();

 

              //

              //                          データ値の読み込み

              //

              fin.open( ifnm );

              double v;

              fin >> v;

              double * x;

              x = new double[nx];

              for (int i = 0; i < nx; i++){

                            fin >> x[i];

              }

              fin >> v;

              double * y;

              y = new double[ny];

              for (int i = 0; i < ny; i++){

                            fin >> y[i];

              }

              fin.close();

                                                                                                                                                                     

              //

              //                          出力ファイルの設定

              //

              cout << "出力ファイル名 = ";

              string ofnm;

              cin >> ofnm;

              ofstream fout( ofnm );

              fout << "入力データ..." << ifnm << endl << endl;

 

              for (int i = 0; i < nx; i++)

              fout << "x[" << i+1 << "] = " << x[i] << endl;

              fout << endl;

              for (int i = 0; i < ny; i++)

              fout << "y[" << i+1 << "] = " << y[i] << endl;

 

              double sx = 0.0;

              for (int i = 0; i < nx; i++) sx += x[i];

              double MeanX = sx / nx;

 

              double sy = 0.0;

              for (int i = 0; i < ny; i++) sy += y[i];

              double MeanY = sy / ny;

 

              double sxx = 0.0;

              for (int i = 0; i < nx; i++) sxx += sqr(x[i] - MeanX);

              double SDX = ::sqrt(sxx / nx);

 

              double syy = 0.0;

              for (int i = 0; i < ny; i++) syy += sqr(y[i] - MeanY);

              double SDY = ::sqrt(syy / ny);

 

              fout << setprecision(5) << fixed << endl;

              fout << "Xの平均      = " << MeanX << endl;

              fout << "Xの分散      = " << sxx/nx << endl;

              fout << "Xの標準偏差  = " << SDX << endl;

              fout << "Xの不偏分散  = " << sxx/(nx-1) << endl;

              fout << "Xの不偏分散の平方根 = " << ::sqrt(sxx/(nx-1)) << endl << endl;

 

              fout << "Yの平均      = " << MeanY << endl;

              fout << "Yの分散      = " << syy/ny << endl;

              fout << "Yの標準偏差  = " << SDY << endl;

              fout << "Yの不偏分散  = " << syy/(ny-1) << endl;

              fout << "Yの不偏分散の平方根 " << ::sqrt(syy/(ny-1)) << endl << endl;

                                                         

              double SDDxy = ::sqrt( (nx * sqr(SDX) + ny * sqr(SDY)) * ((1.0/nx) + (1.0/ny)) / (nx + ny - 2.0) );

              double t = (MeanX - MeanY) / SDDxy;

             

              fout << "Xの平均 - Yの平均 = " << MeanX - MeanY << endl << endl;

              fout << "t = " << t << "      自由度 = " << nx+ny-2 << endl;

 

              fout.close();

              cout << endl << "計算終了" << endl;

              cout << "何か文字を入力して終了" << endl;

              string ckstr;

              cin >>ckstr;

              return 0;

}

==============================================

 

 プログラムソースコードファイルなどをまとめたものは圧縮ファイルt_test_ind.zipとして用意した。圧縮ファイル名t_test_ind.zipをクリックしてダウンロードすることが出来る。ダウンロードした圧縮ファイルt_test_ind.zipはマウスの右ボタンクリックで表示されるメニュから「展開」あるいは「解凍」を選ぶと解凍できる。解凍したファイルはVisual C++2010で開くことができる。

 

 Visual C++プログラミングの入門書として<岡本安晴「大学生のための心理学VC++プログラミング入門」勁草書房>を上梓した。

 

Up