Up

被験者内1要因分散分析

反復要因/繰り返し要因

 

被験者内1要因分散分析(岡本安晴「データ分析のための統計学入門」おうふう)の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行に水準数aと水準内のデータ数(被験者数)nを書く。次の行から、各行に1人の被験者のデータを第1列に第1水準のデータ、・・・、第a列に第a水準のデータというように書く。必要なデータが書かれた後は、読み込みの対象とはならないので、コメントを自由に書くことができる。

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

図2の形式のデータファイルに対する読み込みは、次のコードによって行っている。

 

              int a, n;

              fin >> a >> n;

                                                         

              double ** y;                                     //   データ設定用配列 y[データ番号][水準]

              y = new double*[n];

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

                            y[i] = new double[a];

              double * my;

              my = new double[a];

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

                            for (int j = 0; j < a; j++)

                                          fin >> y[i][j];

              }

              fin.close();

 

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

 

              fout.close();

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

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

              string ckstr;

              cin >>ckstr;

              return 0;

 

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

図3

 

要因Aの水準数が2ケタになっても右側で揃うように、次のようなコードで書き出している。

 

              fout << "データ = " << endl;

              for (int j = 0; j < a; j++){

                            ostringstream sout;

                            sout << "A" << j+1;

                            fout << setw(15) << sout.str();

              }

 

ストリームostringstream型は文字列への書き出し、すなわちメモリ上への書き出しを行う出力用の文字列ストリームであり、書き出された結果はstr( )関数によって文字列として取り出せる。

fout << setw(15)

におけるsetw(15)は、書式(フォーマット)を指定するマニピュレータと呼ばれているものの1つで、setw( k )を出力すると、setw(k)に続く出力はk文字分の長さになるように空白文字を補って出力される。

平均値は、小数点以下2桁の出力に揃えられているが、これは以下のコードによる。

 

              fout << endl << "平均値" << endl;

              fout << setprecision(2) << fixed;

              for (int j = 0; j < a; j++)

                            fout << setw(15) << my_j[j];

              fout << endl;

 

setprecision( s ) << fixed」と続けて出力すると、それ以降の実数値の出力は小数点以下s桁で書き出される。この設定を初期状態に戻すためには

                            fout << resetiosflags(ios_base::floatfield);

を実行する。

 分散分析表は、上で説明したマニピュレータを用いて図3に示されているように右側で揃えた形式で書き出されている。

 

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

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

#include "stdafx.h"                         //            Visual C++が勝手に用意するもの。削除するとエラーになる。

 

#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;

              }

             

              int a, n;

              fin >> a >> n;

                                                         

              double ** y;                       //   データ設定用配列 y[データ番号][水準]

              y = new double*[n];

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

                            y[i] = new double[a];

              double * my;

              my = new double[a];

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

                            for (int j = 0; j < a; j++)

                                          fin >> y[i][j];

              }

              fin.close();

 

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

              string ofnm;

              cin >> ofnm;

              ofstream fout( ofnm );

              fout << "データファイル..." << ofnm << endl << endl;

              fout << "データ = " << endl;

              for (int j = 0; j < a; j++){

                            ostringstream sout;

                            sout << "A" << j+1;

                            fout << setw(15) << sout.str();

              }

              fout << endl << endl;

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

                            for (int j = 0; j < a; j++)

                                          fout << setw(15) << y[i][j];

                            fout << endl;

              }

 

              double * my_i;

              my_i = new double[n];

              double * my_j;

              my_j = new double[a];

 

              double g_my = 0.0;

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

                            my_i[i] = 0.0;

                            for (int j = 0; j < a; j++) my_i[i] += y[i][j];

                            my_i[i] /= double(a);                                     //  被験者iの平均

                            g_my += my_i[i];

              }

              g_my /= double(n);                                                      //  全体の平均

 

              for (int j = 0; j < a; j++){

                            my_j[j] = 0.0;

                            for (int i = 0; i < n; i++) my_j[j] += y[i][j];

                            my_j[j] /= double(n);                                     //  水準jの平均

              }

                                                                                                 

              fout << endl << "平均値" << endl;

              fout << setprecision(2) << fixed;

              for (int j = 0; j < a; j++)

                            fout << setw(15) << my_j[j];

              fout << endl;

                                                                     

              double ss = 0.0;

              double ss_a = 0.0;

              double ss_s = 0.0;

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

                            for (int j = 0; j < a; j++){

                                          ss += sqr(y[i][j] - g_my);

                                          ss_a += sqr(my_j[j] - g_my);

                                          ss_s += sqr(my_i[i] - g_my);

                            }

              }

              double ss_sa = ss - ss_a - ss_s;

 

              //         平均平方和の計算

              double ms_s = ss_s / (n - 1);

              double ms_a = ss_a / (a - 1);

              double ms_sa = ss_sa / ((n - 1) * (a - 1));

 

              double f = ms_a / ms_sa;                //  F値

 

                                                       

              fout << endl << endl;

              fout << setw(35) << "平方和" << setw(15) << "自由度" << setw(15) << "平均平方和" << setw(15) << "F" << endl;

              fout << setprecision(3) << fixed;

              fout << "被験者間      " << setw(15) << ss_s << setw(15) << n-1 << setw(15) << ms_s << endl;

              fout << "要因(主効果)   " << setw(15) << ss_a << setw(15) << a-1 << setw(15) << ms_a << setw(15) << f << endl;

              fout << "残差(交互作用)  " << setw(15) << ss_sa << setw(15) << (n-1)*(a-1) << setw(15) << ms_sa << endl;

 

              fout.close();

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

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

              string ckstr;

              cin >>ckstr;

              return 0;

}

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

 

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

 

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

 

Up