2変量統計量の計算

C++Builderネイティブ・コンソール・アプリケーション

 

2変量統計量(相関係数、共分散)をそれぞれの変量の1変量統計量(平均、分散、標準偏差)とともに算出するコンソール・アプリケーションを作成した。プログラムのそーす・ファイルなどはまとめて圧縮ファイルCalcStat2Vars.zipとして用意した。ファイル名をクリックしてダウンロードし、マウスの右ボタンクリックで表示されるメニュから「解凍」あるいは「展開」を選ぶと解凍できる。解凍したプログラムをC++Builderで開いて実行すると、コンソール・ウィンドウが開き(図1)、入力データファイル名の設定が求められる。

図1 コンソール・ウィンドウ

 

C++Builderのコンソールアプリケーションの実行時のcurrent folderはソースファイルなどが格納されているフォルダの1つ下Debugフォルダであるので、データファイルなどがソースファイルと同じフォルダにあるときは、データファイル名の前に「..\」を付けて、1つ上のフォルダであることを示す。例えば、「..\Data.txt」とする。出力ファイルも同じフォルダに置くときは「..\」を付ける。例えば、実行時のコンソールの例(図1)では、出力ファイル名を「..\temp.txt」としている。

 テキストファイルは、1行単位で読み込むためのクラス型RdTxtLnをヘッダーファイルmyLib.hに用意して、そのメンバ関数readlineによって行っている。すなわち、入力ファイル名がstring型変数fin_nmに設定されているとき、

RdTxtLn rd( fin_nm );

とクラス型の変数rdを定義することにより、

rd.readline( s );

string型変数sを引数として関数readlineを呼び出すと、1行分のデータがsに設定される。クラス型RdTxtLnには、他にファイルを開くメンバ関数open、閉じるための関数closeが用意されている。クラス型RdTxtLnのコードは、このページの最後にmyLib.hのリストを付けておいたので参照されたい。

 データは、1行に2変量の値が対で書かれているという形式で用意する(図2)。

無題.jpg

図2 データの形式

 

図2の例では、(1, 5)から(5, 8)までの5組のデータが書かれている。データは、スラッシュ「/」で始まる行の次の行から書かれ、スラッシュ「/」で始まる行で入力データの終わったことが示されるという形式である。

 読み込まれた1行分のデータからipos番目のデータを取り出すための関数SeekStrを用意している。関数ヘッダーは

string SeekStr( string s, int ipos );

となっている。取り出されたデータは文字列であるので、これの表わす数値への変換のために関数strToDoubleを用意している。関数ヘッダーは

double strToDouble( string s );

となっている。

 これらの関数を用いてプログラムCalcStat2Vars.cppは、直感的に判り易く書かれているが、そのソースコードをヘッダーファイルmyLib.hとソースコードmyLib.cppとともに以下に示す。

 

========== CalcStat2Vars.cpp ===============

#include <cmath>

#include <iostream>

#include <fstream>

#include "myLib.h"

 

using namespace std;

using namespace myLib;

 

#pragma argsused

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

{

              //

              //    入力用テキストファイル名と入力ストリームの設定

              //

              cout << "Input data file = ";

              string fin_nm;

              cin >> fin_nm;

              RdTxtLn rd( fin_nm );

              if (rd.iCond != 0){

                            cout << "To open input data file failed." << endl;

                            return 9;

              }

 

              //

              //    出力用テキストファイル名と出力ストリームの設定

              //

              cout << "Output file = ";

              char  fout_nm[200];

              cin >> fout_nm;

              ofstream fout( fout_nm );

              fout << "Input data file = " << fin_nm << endl << endl;

 

              //

              //    入力ファイルの先頭部分("/"で始まる行まで)の読み飛ばし

              //

              string s;

              int ick = 0;

              do{

                            rd.readline( s );

                            if (s.size() > 0)

                                          if (s[0] == '/') ick = 1;

              }while( ick == 0 );

 

              //

              //   データ数Nを数える

              //

              int N = 0;

              ick = 0;

              do {

                            rd.readline( s );

                            if (s[0] == '/'){

                            ick = 1;

                            } else {

                                          N++;

                            }

              } while (ick == 0);

 

              //

              //   入力ファイルの先頭に読み込み位置を戻す

              //

              rd.close();

              rd.open(fin_nm);

              if (rd.iCond != 0){

                            cout << "To re-open the inpur file failed." << endl;

                            return 9;

              }

 

              ick = 0;

              do {

                            rd.readline( s );

                            if (s.size() > 0)

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

                                                        ick = 1;

              } while (ick == 0);

 

              double * x, * y;

              x = new double[N];

              y = new double[N];

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

                            rd.readline( s );

                            x[i] = strToDouble(SeekStr(s, 0));

                            y[i] = strToDouble(SeekStr(s, 1));

              }

              fout << "\n" << "Data..." << endl;

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

                            fout << i << ": x = " << x[i] << "  \ty = " << y[i] << endl;

              }

 

              double sx = 0.0;

              double sy = 0.0;

              double sxx = 0.0;

              double syy = 0.0;

              double sxy = 0.0;

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

                            sx += x[i];

                            sy += y[i];

                            sxx += sqr(x[i]);

                            syy += sqr(y[i]);

                            sxy += x[i] * y[i];

              }

              double meanX = sx / N;

              double meanY = sy / N;

              double varX = (sxx / N) - sqr(meanX);

              double varY = (syy / N) - sqr(meanY);

              double sdX = sqrt(varX);

              double sdY = sqrt(varY);

              double Cov = (sxy / N) - (meanX * meanY);

              double r = Cov / (sdX * sdY);

 

              fout << endl;

              fout << "mean of x = " << meanX << endl;

              fout << "mean of y = " << meanY << endl;

              fout << "Variance of x = " << varX << endl;

              fout << "Variance of y = " << varY << endl;

              fout << "SD of x = " << sdX << endl;

              fout << "SD of y = " << sdY << endl;

              fout << "Covarince = " << Cov << endl;

              fout << "Correlation = " << r << endl;

 

              double uvarX = N * varX / (N - 1);

              double uvarY = N * varY / (N - 1);

              double uCov  = N * Cov / ( N - 1);

 

              fout << endl;

              fout << "Unbiased Var of x = " << uvarX << endl;

              fout << "Unbiased Var of y = " << uvarY << endl;

              fout << "Unbiased Cov = " << uCov << endl;

              fout << "SD(uVarX) = " << sqrt(uvarX) << endl;

              fout << "SD(uVarY) = " << sqrt(uvarY) << endl;

 

              rd.close();

              fout.close();

              delete [] x;

              delete [] y;

 

              return 0;

}

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

 

=========== myLib.h ===================

#ifndef MYLIB_CK

#define MYLIB_CK

 

//    2009.01  Y.Okamoto

 

#include <iostream>

#include <fstream>

#include <sstream>

 

namespace myLib {

 

using namespace std;

 

//

//                          x の平方を返す

//

double sqr( double x );

 

 

//

//  文字列sの表す整数値を返す

//

int strToInt( string s );

 

 

//

//   文字列sの表す実数値を返す

//

double strToDouble( string s );

 

 

bool check_c( char c );

 

 

 //

 //  空白で区切られた文字列からなるstrings

 //  含まれるipos番目の文字列を返す

 //

 string SeekStr( string s, int ipos );

 

 

 

 //

 //   テキストファイルから1行ごとに読み込むためのクラス型

 //

 class RdTxtLn {

 public:

   FILE * fin;

   int iCond;  //  0: OK,  1: End of File,  9: Open Error, -1: Not initialized

   string s;

 

   RdTxtLn(): iCond(-1) {}

 

   //

   //    nmに読み込み用テキストファイル名を設定

   //    オープンに成功すればiCondの値は0が設定される。

   //

   RdTxtLn( string nm ): iCond(0){

     fin = fopen( nm.c_str(), "r" );

     if (fin == NULL) {

       iCond = 9;

       return;

     } else {

       iCond = 0;

       return;

     }

    

   }

 

   virtual ~RdTxtLn(){

     if (iCond == 0) fclose(fin);

  }

 

   void open( string nm ){

     fin = fopen( nm.c_str(), "r" );

     if (fin == NULL) {

       iCond = 9;

       return;

     } else {

       iCond = 0;

       return;

     }

    

   }

 

  

   void close(){

     if (iCond == 0){

       fclose(fin);

       iCond = -1;

     }

   }

 

   //

   //   メソッドreadlineを1回呼び出すと

   //   ファイルから1行分がstrに読み込まれる

   //

   int readline( string & str ){

     int v = 0;

     if (iCond != 0){

       v = 1;

       return v;

     }

     const int maxN = 1000;

     char c[maxN];

     int ipos = 0;

     int cv;

     while (true){

       cv = fgetc(fin);

       if (cv == EOF){

               c[ipos] = 0;

               str = "";

               if (ipos > 0)

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

                   str += c[i];

               iCond = 1;

               return v;

       }

       switch (char(cv)){

       case '\r': break;

       case '\n': c[ipos] = 0; ipos *= -1; break;

       default  : c[ipos] = char(cv);

                              ipos++;

                              if (ipos > (maxN-2)){

                                c[maxN-1] = 0;

                                v = 9;

                                return v;

                              }                        

                              break;

       }

       if (ipos <= 0) {

               ipos *= -1;

               str = "";

               if (ipos > 0)

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

                   str += c[i];

               v = 0;

               return 0;

       }

     }

   }

 

 };

 

}  //  myLib

 

#endif

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

 

============= myLib.cpp ================

//    2009.01  Y.Okamoto

 

#include <iostream>

#include <fstream>

#include <sstream>

#include "myLib.h"

 

namespace myLib {

 

using namespace std;

 

 

double sqr( double x ){

   return x * x;

}

 

 

 //

 //  文字列sの表す整数値を返す

int strToInt( string s ){

  istringstream istrm(s);

  int i;

  istrm >> i;

  return i;

}

 

//

//   文字列sの表す実数値を返す

//

double strToDouble( string s ){

  istringstream istrm(s);

  double d;

  istrm>> d;

  return d;

}

 

 

 bool check_c( char c ){

   if ( (c == ' ') || (c == '\t') ){

     return true;

   } else {

     return false;

   }

 }

 //

 //  空白で区切られた文字列からなるstrings

 //  含まれるipos番目の文字列を返す

 //

 string SeekStr( string s, int ipos ){

   string vstr = "";

   int sLength = s.size();

   if (sLength <= 0){

     return vstr;

   }

   int istart, iend;

   if (ipos == 0){

     istart = 0;

     while( check_c(s[istart]) && (istart < sLength-1) ) istart++;

     if (istart == sLength-1){

       if (! check_c(s[istart])) vstr += s[istart];

       return vstr;

     }

     //     }

     iend = istart+1;

       while ( (! check_c(s[iend])) && (iend < sLength-1) ) iend++;

       if (check_c(s[iend])) iend--;

     for (int i = istart; i <= iend; i++)

       vstr += s[i];

     return vstr;

   }

 

   if (ipos > 0){

     int istart = 0;

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

       while( check_c(s[istart]) && (istart < sLength-1) ) istart++;

       if (istart == sLength-1) return "";

       int iend = istart;

       while ( (! check_c(s[iend])) && (iend < sLength-1) ) iend++;

       if (iend == sLength-1) return "";

       istart = iend+1;

     }

 

     while( check_c(s[istart]) && (istart < sLength-1) ) istart++;

     if (istart == sLength-1)

       if (! check_c(s[istart])){

               vstr = s[istart];

               return vstr;

       }else{

               return "";

       }

     iend = istart;

               while ( (! check_c(s[iend])) && (iend < sLength-1) ) iend++;

               if (check_c(s[iend])) iend--;

     for (int i = istart; i <= iend; i++)

       vstr += s[i];

     return vstr;

   }

 

   return vstr;

 }

 

}  //  mylib

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