数量化I類プログラムquant1.c
/* 多変量統計解析法 第4章 §2数量化T類(pp.139-151) (河口至商、多変量解析入門T、森北出版、1973、pp.95-107) quant1.c 数量化T類, 1994.01.20, 1998.1.29, 1999.2.18 z.sekiya */ /* A. プログラム仕様 program spec (quant1.c) 1) 入力 input: title:タイトル, n:サンプル数sample size, ns:アイテム数items , kn[]:カテゴり数 categorys y,jz[n][ns] 2) 処理 process: x:データ行列, v(<= x'x):生の積和行列 , 掃出しsweep out, カテゴり毎の標準化normalize category weight x: データ行列(ダミー変数dummy variable,外的基準y,定数1) 3) 出力 output: 外的基準y,jz, データ行列x, 積和行列v, v^-1, カテゴリスコア, 範囲 予測値、誤差、重相関係数、偏相関係数 B. 処理手順 plan 1) データファイル名の入力 Input file name 2) データの読み込み read from file ( title, parameters, data ) 3) データ行列xへのセット set x 4) 積和行列、分散の計算 calculate v, print v 5) 掃き出し sweep s, print s 6) カテゴリ毎の標準化 normalise category weight, print b, bh 7) 予測値と誤差の計算・表示 y, yhat, e 8) 標本行列 X、生の積和行列 rs(x'x),積和行列 s(x'x)の計算 9) 相関行列 R(x'x), 偏相関係数 sweep out for pr1. (compile and link) >cl quant1.c sweep.obj 2. (Execution) >quant1 (file name needed for data input ?) file_name */ #include #include #include #define LA 12 #define LN 30 void sweep(double a[][LA], int k, int ii); // 掃き出し void correl(double s[][LA], int jj, double r[][LA]); // 相関係数の計算 void matprt(char name[], char title[], double a[][LA], int im, int jm);// 行列表示 matprod(double x[][LA],int n, int nnp2, double v[][LA]) // 生の積和行列の計算 { int i, j, l; double vjl; for(j=1; j<=nnp2; j++) { for(l=1; l<=nnp2; l++) { vjl=0.0; for(i=1;i<=n; i++) vjl=vjl+x[i][j]*x[i][l]; v[j][l]=vjl; } } } main() // 数量化T類,main関数 { char fname[30], title[60], *pa, aster[5]; int i, j, k,kk, l, m, n, ns, kn[LA], kc, nn, nnp1, is, jz[LN][LA], nnp2, jcz[LA][LA], freq[LA], freq1[LA], nsp1, nsp2; double yb, y[LN], yy[LN],e[LN], x[LN][LA], v[LA][LA], yhat, vjl, bh[LA], xb[LA], aij[LA][LA], an[LA][LA], sumc[LA], anmax[LA],anmin[LA],anrange,y2,yh2, s[LA][LA], pr[LA], r[LA][LA]; FILE *fp1; long nowtime; time(&nowtime); pa = ctime(&nowtime); *(pa+24)='\0'; printf("<%s>\n", pa); /* 1) データファイル名の入力 Input file name */ do { printf("<< 数量化T類(quant1) k134084 関谷 >> Input ファイル名:");scanf("%s", fname); fp1 = fopen(fname,"r"); } while(fp1 ==NULL) ; /* 2) データの読み込み read from file (title, parameters, data ) */ /* 3) データ行列xへのセット set x */ fscanf(fp1, "%s %d %d",title, &n, &ns); for(i=1; i<=ns; i++) fscanf(fp1, "%d", &kn[i]); printf("\nタイトル<%s>\nサンプル数(n):%d アイテム数(ns):%d \n", title, n, ns); printf(" アイテム毎のカテゴリ数(kn[i]) "); kc=0; for(i=1; i<=ns; i++) { printf(" kn[%d]:%d ", i, kn[i]); kc += kn[i]; } nn = kc - ns + 1; nnp1 = nn + 1; nnp2=nnp1+1; printf("\n ダミー変数の数(kc += kn[i]):%d\n", kc); printf("\n 方程式の実際の変数の数(nn=kc-ns+1):%d\n", nn); printf(" 変数添え字への変換テーブルjcz[アイテム][カテゴリ]\n"); k=0; for(i=1;i<=ns;i++) for(j=1;j<=kn[i]; j++) { // これでデータ行列Xをセットする if(j==1 && i>1) jcz[i][j] = 0; else jcz[i][j] = ++k; printf(" jcz[%d][%d]:%d ",i,j, jcz[i][j]); } printf("\n 方程式の実際の変数の数の確認(k):%d\n", k); printf("\nサンプルデータの読み込み\n"); printf(" サンプル番号(i) 目的変数(y[i]) アイテムjのカテゴリ番号jz[i][1] "); for (j=2; j<=ns; j++) printf(" jz[i][%d] ", j); for(i=1; i<=n; i++){ for(k=1;k<=nn; k++) x[i][k]=0.0; x[i][nnp2]=1.0; fscanf(fp1, "%d %lf", &kk, &x[i][nnp1]); y[i]= x[i][nnp1]; printf("\n i:%2d y[i]: %f ", kk, x[i][nnp1]); for(j=1;j<=ns;j++){ fscanf(fp1, "%d", &jz[i][j]);printf(" jz[%2d][%d]:%d ", i, j, jz[i][j]); x[i][(jcz[j][(jz[i][j])])]=1.0; // データ行列へのセット } } printf("\n\nダミー変数への代入 x[i][(jcz[j][(jz[i][j])])]=1.0;\n"); printf("アイテムNo "); // 行の見出し(データ行列 X) for (i=1;i<=ns; i++){ for (j=1; j<=kn[i]; j++){ if (i>1 && j ==1) continue; printf(" %d ", i); } } printf(" 目的変数y ダミー変数\nカテゴリNo "); for (i=1;i<=ns; i++){ for (j=1; j<=kn[i]; j++){ if (i>1 && j ==1) continue; printf(" %d ", j); } } matprt("(quant1.c)データ行列 X seted", title, x, n, nnp2); /* 4) 積和行列、分散の計算 v=x'x */ matprod(x,n,nnp2, v); matprt("積和行列 v(x'x)", title, v, nnp2, nnp2); for(i=1;i<=nn;i++) { freq[i]=v[nnp2][i]; // カテゴリの度数 xb[i]=freq[i]/(float)n; // カテゴリの相対度数 } yb=v[nnp2][nnp1]/n; // 目的関数の平均,定数項である /* 5) 掃き出し sweep out */ for (k=1; k<=nn; k++) { sweep(v, k, nnp2); } matprt("掃き出し後の v-1 ", title, v, nnp2, nnp2); /* 6) カテゴリ毎の標準化 normalise category weight, print b, bh */ k=1; for(i=1;i<=ns; i++){ sumc[i]=0.0; freq1[i]=n; anmax[i]=-10000.0; anmin[i]=10000.0; for(j=1;j<=kn[i];j++) { if(i>1 && j==1) { an[i][j]=0.0; // アイテムiカテゴリjへの係数 } else { an[i][j]=v[k++][nnp1]; // 正規方程式の解 sumc[i] += an[i][j]*xb[k-1]; // 相対度数との積和(アイテム毎) freq1[i] -= freq[k-1]; // アイテム毎のカテゴリ1の度数 } aij[i][j]=an[i][j]; // 偏相関係数のため if(an[i][j] >anmax[i]) anmax[i]=an[i][j]; // アイテム内最大の係数 if(an[i][j] 1) { printf(" %d %2d %10.2f\n", j, freq1[i], an[i][j]); }else printf(" %d %2d %10.2f\n", j, freq[k++], an[i][j]); } } printf(" 定数項(yの平均:yb): %8.2f\n", yb); /* 7) 予測値と誤差の計算・表示 y, yhat, e、print yhat, e */ printf("\n<< 予測誤差など[ %s ] >>>\n No. 観測値 予測値 誤差 \n", title); y2=yh2=0.0; for(i=1;i<=n;i++){ yhat = yb; for(j=1; j<=ns; j++) { k=jz[i][j]; yhat = yhat + an[j][k]; } e[i]= y[i]-yhat; printf(" %2d %6.2f %6.2f %6.2f ", i, y[i], yhat, e[i]); y2 += (y[i]-yb)*(y[i]-yb); yh2 += (yhat-yb)*(yhat-yb); for(j=1;j<=ns;j++) printf(" %2d", jz[i][j]); printf("\n"); } printf("\n 重相関係数 Ry12...m: %6.3f\n", sqrt(yh2/y2)); /* 8) 標本行列 X、生の積和行列 rs(x'x),積和行列 s(x'x)の計算 */ nsp1=ns+1; nsp2=ns+2; for(i=1; i<=n; i++){ for(j=1; j<=ns; j++) x[i][j] = aij[j][jz[i][j]]; // アイテム得点 x[i][nsp1] = y[i]; // 目的関数 x[i][nsp2] = 1.0; // 定数項 } matprt("標本行列 X(アイテム得点1,2,..,m,y,1.0)",title, x, n, nsp2); matprod(x,n,nsp2, s); matprt(" 生の積和行列 rs(x'x)", title, s, nsp2, nsp2); sweep(s,nsp2,nsp2); matprt(" 積和行列 s(x'x)", title, s, nsp2, nsp2); /* 9) 相関行列 R(x'x), 偏相関係数 sweep out for pr */ correl(s,nsp1,r); matprt(" 相関行列 R(x'x)", title, r, nsp1, nsp1); for (k=1; k<=nsp1; k++) sweep(r, k, nsp1); matprt("掃き出し後 R-1 ", title, r, nsp1, nsp1); for(i=1;i<=ns;i++) pr[i]=-r[i][nsp1]/sqrt(r[i][i]*r[nsp1][nsp1]); printf("\n<偏相関係数> \n"); for(i=1; i<=ns; i++) printf(" pr(y,%d):%7.3f\n", i, pr[i]); printf("\n\n"); } /* 以下は、実行例(qut1.out)を参照のこと */