平均値の差のt検定:対応のあるデータの場合
対応のあるデータ(繰り返しデータ)の平均値の差の検定(t test)(岡本安晴「データ分析のための統計学入門」おうふう)を行うVisual C++/win32プログラムを作成した。なお、Win32コンソールアプリケーションの新規作成については<Win32コンソールアプリケーションの新規作成>で、C++の標準入出力(コンソール入出力)については<標準入出力cinとcout>で、C++におけるテキストファイル入出力については<テキストファイル入出力>で説明している。
プログラムの実行例を図1に示す。
図1
入力ファイルはプログラム・ソースコード・ファイル*.cppと同じフォルダに用意する。
入力データファイル設定のソースコードは以下のようになっている。
cout << "入力データファイル = " ;
string ifnm;
cin >> ifnm;
ifstream fin( ifnm );
if ( ! fin){ // 入力ファイルの設定が失敗するとfinはfalseを返す。
cout << "入力ファイルエラー" << endl;
cout << "何か文字を入力して終了。" << endl;
string s;
cin >> s;
return 9;
}
入出力ストリーム・オブジェクトの変数finを条件式に用いると、ストリームに何かエラーがあるとfalseが返される。
入力ファイルは図2の形式で用意する。
図2
第1行に基準値を書く。データ、は基準値の書かれた行の次の行から書き、最後のデータ、の次の行に基準値より小さい値を書いて、データの区切りとする。
エディタでデータを新しく用意したときは、保存してからプログラムで読み込む。エディタの画面に打ち込んだだけでは、その内容はファイルに反映されない。
基準値をもとに読み込むデータ数を数えているが、以下のコードによって行っている。
double c;
fin >> c;
int n = 0;
double v;
do{
fin >> v;
if(v < c) break;
fin >> v;
n++;
}while(true);
fin.close();
データ数のカウント後、入力用ストリームを開きなおして、以下のようにデータの読み込みを行っている。
double * x, * y;
x = new double[n];
y = new double[n];
fin.open( ifnm );
fin >> v;
for (int i = 0; i < n; i++)
fin >> x[i] >> y[i];
fin.close();
データの読み込み後、t検定のためのt値の計算が行われる。t値は以下のコードで求めている(岡本安晴「データ分析のための統計学入門」おうふう)。
double sdd = 0.0;
for (int i = 0; i < n; i++)
sdd += sqr(x[i] - y[i] - MeanD);
double SD = ::sqrt(sdd / n);
double t = MeanD / (SD / ::sqrt(n - 1.0));
計算を終えて結果の書き出しが終了すると「何か文字を入力して終了」と表示されるので、適当な文字キーを押してEnterキーを押すとプログラムの終了となる。この部分は以下のコードによって処理されている。
fout.close();
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桁の出力となる。
プログラムソースコード全体は以下の通りである。
==============================================
#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){ // 入力ファイルの設定が失敗するとfinはfalseを返す。
cout << "入力ファイルエラー" << endl;
cout << "何か文字を入力して終了。" << endl;
string s;
cin >> s;
return 9;
}
double c;
fin >> c;
int n = 0;
double v;
do{
fin >> v;
if(v < c) break;
fin >> v;
n++;
}while(true);
fin.close();
double * x, * y;
x = new double[n];
y = new double[n];
fin.open( ifnm );
fin >> v;
for (int i = 0; i < n; i++)
fin >> x[i] >> y[i];
fin.close();
//
// 出力ファイルの設定
//
cout << "出力用ファイル名 = ";
string ofnm;
cin >> ofnm;
ofstream fout( ofnm );
fout << "データファイル = " << ifnm << endl << endl;
fout << "データ..." << endl;
for (int i = 0; i < n; i++){
fout << "X[" << i+1 << "] = " << setw(10) << x[i] << setw(15) << "y[" << i+1 << "] = " << y[i] << endl;
}
double sx = 0.0, sy = 0.0;
for (int i = 0; i < n; i++){
sx += x[i];
sy += y[i];
}
double MeanX = sx / n;
double MeanY = sy / n;
double sxx = 0.0, syy = 0.0;
for (int i = 0; i < n; i++){
sxx += sqr(x[i] - MeanX);
syy += sqr(y[i] - MeanY);
}
double SDX = ::sqrt(sxx / n);
double SDY = ::sqrt(syy / n);
fout << setprecision(5) << fixed << endl << endl;
fout << "Xの平均 = " << MeanX << endl;
fout << "Xの分散 = " << sxx/n << endl;
fout << "Xの標準偏差 = " << SDX << endl;
fout << "Xの不偏分散 = " << sxx/(n-1) << endl;
fout << "Xの不偏分散の平方根 = " << ::sqrt(sxx/(n-1)) << endl << endl;
fout << "Yの平均 = " << MeanY << endl;
fout << "Yの分散 = " << syy/n << endl;
fout << "Yの標準偏差 = " << SDY << endl;
fout << "Yの不偏分散 = " << syy/(n-1) << endl;
fout << "Yの不偏分散の平方根 " << ::sqrt(syy/(n-1)) << endl << endl;
double MeanD = MeanX - MeanY;
fout << endl << "Xの平均 - Yの平均 = " << MeanD << endl;
double sdd = 0.0;
for (int i = 0; i < n; i++)
sdd += sqr(x[i] - y[i] - MeanD);
double SD = ::sqrt(sdd / n);
double t = MeanD / (SD / ::sqrt(n - 1.0));
fout << endl;
fout << "t = " << t << " 自由度 = " << n-1 << endl;
fout.close();
cout << endl << "計算終了" << endl;
cout << "何か文字を入力して終了" << endl;
string ckstr;
cin >>ckstr;
return 0;
}
==============================================
プログラムソースコードファイルなどをまとめたものは圧縮ファイルt_test_rep.zipとして用意した。圧縮ファイル名t_test_rep.zipをクリックしてダウンロードすることが出来る。ダウンロードした圧縮ファイルt_test_rep.zipはマウスの右ボタンクリックで表示されるメニュから「展開」あるいは「解凍」を選ぶと解凍できる。解凍したファイルはVisual C++2010で開くことができる。
Visual C++プログラミングの入門書として<岡本安晴「大学生のための心理学VC++プログラミング入門」勁草書房>を上梓した。