上へ

被験者内1要因分散分析

 

被験者内1要因(繰り返し要因、反復要因)分散分析のためのVisual C++プログラムを作成した。この分散分析については<岡本安晴「データ分析のための統計学入門」2009、おうふう;第4章:分散分析>などを参照されたい。プログラムは、ウェブサイト<テキストファイル入出力>で説明したプログラムに下記のようにコードを書き加えて作成した。

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

        //

        //              pos 番目の文字列の取り出し

        //

        String ^ SeekStr( String ^ str, int pos ){

                String ^ vstr = "";

                array<wchar_t> ^ separator = { ' ', '\t', ',',' ','/' };

                array<String ^> ^ ary_str;

                ary_str = str->Split( separator );

                int L = ary_str->Length;

                int ckp = -1;

                int tmpPos = 0;

                do {

                        if (ary_str[tmpPos]->Length > 0) ckp++;

                        tmpPos++;

                } while ((ckp != pos) && (tmpPos < L) );

                if (ckp == pos) vstr = ary_str[tmpPos-1];

 

                return vstr;

        }

 

        double sqr( double v ){

                        return v * v;

        }

       

        private: System::Void button1_Click(System::Object^  sender, System::EventArgs^  e) {

                                 //

                                 //             入出力ファイルの名の設定

                                 //

                                 openFileDialog1->Title = "入力データファイル名";

                                 if (openFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::Cancel) return;

                                 saveFileDialog1->Title = "出力ファイル名";

                                 if (saveFileDialog1->ShowDialog() == System::Windows::Forms::DialogResult::Cancel) return;

 

                                 using namespace System::IO;

                                 //

                                 //             入力ストリームと出力ストリームの設定

                                 //

                                 StreamReader ^ fin = gcnew StreamReader( openFileDialog1->FileName, System::Text::Encoding::GetEncoding("shift-jis") );

                                 StreamWriter ^ fout = gcnew StreamWriter( saveFileDialog1->FileName, false, System::Text::Encoding::GetEncoding("shift-jis") );

 

                                 fout->WriteLine("Data file..." + openFileDialog1->FileName);

                                 fout->WriteLine();

 

                                 String ^s;

                                 while(true){

                                         s = fin->ReadLine();

                                         if (s->Length > 0)

                                                 if (s[0] == '/') break;

                                 }

                                 s = fin->ReadLine();

                                 int a = int::Parse(SeekStr(s, 0));

                                 int n = int::Parse(SeekStr(s, 1));

 

                                 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++){

                                         s = fin->ReadLine();

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

                                                 y[i][j] = double::Parse(SeekStr(s, j));

                                 }

 

                                //         データの書き出し

                                fout->WriteLine("データ= ");

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

                                        fout->Write(("A" + (j+1).ToString())->PadLeft(15));

                                fout->WriteLine();

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

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

                                                fout->Write( (y[i][j].ToString("F2"))->PadLeft(15) );

                                        fout->WriteLine();

                                }

 

                                 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->WriteLine();

                                fout->WriteLine("平均値");

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

                                        fout->Write(my_j[j].ToString("F3")->PadLeft(15));

                                fout->WriteLine();

 

                               

 

                                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->WriteLine();

                                fout->WriteLine();

                                fout->WriteLine(String(" ").PadLeft(20) + String(" ").PadLeft(9) + "平方和" +

                                                                String(" ").PadLeft(9) + "自由度" + String(" ").PadLeft(5) + "平均平方和" +

                                                                String("F").PadLeft(15) );

                                fout->WriteLine("被験者間      " + ss_s.ToString("F2")->PadLeft(15) +

                                                                (n-1).ToString()->PadLeft(15) + ms_s.ToString("F3")->PadLeft(15) );

                                fout->WriteLine("要因(主効果)   " + ss_a.ToString("F2")->PadLeft(15) +

                                                                (a-1).ToString()->PadLeft(15) + ms_a.ToString("F3")->PadLeft(15) +

                                                                f.ToString("F3")->PadLeft(15) );

                                fout->WriteLine("残差(交互作用)  " + ss_sa.ToString("F2")->PadLeft(15) +

                                                                ((n-1)*(a-1)).ToString()->PadLeft(15) + ms_sa.ToString("F3")->PadLeft(15) );

 

                                 fout->Close();

                                 MessageBox::Show(saveFileDialog1->FileName + " was saved.");

                                 Close();

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

このプログラムを実行すると図1のウィンドウが表示される。

図1

 

button1」ボタンのクリックで入力データ名設定用ダイアログウィンドウが図2のように表示される。

図2

 

入力データファイル名を指定して「開く」ボタンをクリックすると、計算結果出力用のファイル名設定を求めるダイアログウィンドウが表示される(図3)。

図3

 

出力はテキストファイルとして書き出されるので、ファイル名の拡張子は「.txt」としておく。出力ファイル名の設定後、「保存」ボタンをクリックすると計算がはじまり、計算終了後図4のメッセージウィンドウが表示される。

図4

 

メッセージウィンドウの「OK」ボタンのクリックでプログラムが終了する。

入力データは、図5に示すようにスラッシュ/で始まる行の次の行に、まず水準数と被験者数を書く。

図5

 

次の行から、各行に各水準のデータを並べて書く。被験者内要因なので水準間のデータは対応がある。各行に一人のデータ(あるいは対応のあるデータの組み、繰り返しの1組)を並べて書く。同じ水準のデータは同じ列に並ぶようにする。図5の場合、被験者1のデータが80(水準1), 110(水準2), 120(水準3)と並んでいる。5人目の被験者のデータは70(水準1), 95(水準2), 105(水準3)である。

図5のファイルを入力データとしたときの出力ファイルは次のようになっている。

 

============ 出力ファイル例:ここから ====================

Data file...F:\yasuharu\www\LaCoocan\introprg\ANOVA1wthn\anova1wthn\anova1wthn\DataANOVA1wthn.txt

 

データ=

             A1             A2             A3

          80.00         110.00         120.00

         150.00         170.00         200.00

          90.00         100.00         120.00

          95.00         105.00         110.00

          70.00          95.00         105.00

 

平均値

         97.000        116.000        131.000

 

 

                             平方和        自由度    平均平方和             F

被験者間            13306.67              4       3326.667

要因(主効果)          2903.33              2       1451.667         25.065

残差(交互作用)          463.33              8         57.917

============ 出力ファイル例:ここまで========================

 

プログラム・ファイルは圧縮ファイルanova1wthn.zipとしてまとめた。ファイル名anova1wthn.zipをクリックしてダウンロードしたものをマウスの右ボタンクリックで表示されるメニュ「解凍」あるいは「展開」などを選ぶと解凍できる。解凍したものはVisual C++などで開いてビルド実行することができる。実行形式ファイルanova1wthn.exeも用意したので、ファイル名anova1wthn.exeをクリックしてダウンロード実行することができる。実行形式ファイルは.NET Framework3.5対応である。

なお、F値に対応する確率を求めるVisual C++プログラムはウェブサイト<エフ分布>に用意した。

 

上へ