標準化した分割表
先日、Staged approachデータをJoint analysisする件についての記事を書いた(こちら)。その中で、Staged approachでの各ステージでのサンプルサイズは、ケース・コントロールで同数であるものとして統計量を求め、その値の関係を論じた(引用文献に準拠)。そのとき、ケース・コントロールのサンプルサイズが異なる場合に生じる注意点は、Staged approachの問題というよりも、分割表検定そのものに由来することだという1文を書いた。
今日の記事はそれに関する記事である。記載を検証するエクセルはこちら
それに用いたJavaソースは記事の末尾
- 分割表における検定標準化1(普通の標準化)
- この標準化の妥当性
- この標準化の妥当性の根拠
- 標準化1’
- 2x2分割表は縦と横について対称なので、ケース・コントロール軸で標準化してもカイ自乗値が変わらないのなら、要因の軸について標準化しても変わらないはずで、確かに変わらない
- もちろん(ad-bc)/nの値はこの標準化によって変わっていない
- 標準化2
- 2x2分割表の2軸のどちらについて標準化してもカイ自乗値が変わらないのなら、両軸について標準化することもできそうである
- 両軸について標準化するとは、e=fかつg=hということである
- この条件はa=dかつb=cに他ならない
- 今、標準化1と標準化1’において重要だったのは、(ad-bc)/nを変えないことであった
- 標準化2においてもこの条件を満足させることとする
- この条件は、a=d, b=cの値について、それぞれ、aとd、bとcの相乗平均(SQRT(axd),SQRT(bxc))によって、a''=d'',b''=c''を求め、その値について、総和(n''=a''+b''+c''+d'')をとり、x'=x''*n/n''なる値をa',b',c',d'とすることによって実現される
- この標準化により、周辺度数(e',f',g',h')のすべてが等しくなっていることに注意する
- 標準化が2重に行われているので、2x2度数の偏りが非常に強かったり、セルの期待度数が小さい場合には、標準化1、標準化1’に比べて値の違いの大きい場合もあるが、十分に相関していると言える
- ソース
public class StandardizedChi {
public static double[][] StandardCaseCont(int[][] d){
double[][] ret = new double[d.length][d[0].length];
int[] marginal1 = marginal1(d);
int[] marginal2 = marginal2(d);
double[] ncasecont = new double[d.length];
for(int i=0;i<ncasecont.length;i++){
ncasecont[i] = (double)marginal1[i];
}
double nh = Calculator.harmonicMean(ncasecont);
for(int i=0;i<ret.length;i++){
for(int j=0;j<ret[i].length;j++){
ret[i][j] = (double)d[i][j]*nh/ncasecont[i];
}
}
return ret;
}
public static double[][] StandardFactor(int[][] d){
double[][] ret = new double[d.length][d[0].length];
int[] marginal1 = marginal1(d);
int[] marginal2 = marginal2(d);
double[] ncasecont = new double[d[0].length];
for(int i=0;i<ncasecont.length;i++){
ncasecont[i] = (double)marginal2[i];
}
double nh = Calculator.harmonicMean(ncasecont);
for(int i=0;i<ret.length;i++){
for(int j=0;j<ret[i].length;j++){
ret[i][j] = (double)d[i][j]*nh/ncasecont[j];
}
}
return ret;
}
public static double[][] StandardBoth(int[][] d){//2x2table Only
double[] adV = {(double)d[0][0],(double)d[1][1]};
double[] bcV = {(double)d[0][1],(double)d[1][0]};
double ad = Calculator.geometricMean(adV);
double bc = Calculator.geometricMean(bcV);
//System.out.println("ad bc " + ad + " " + bc);
double sumOriginal=0;
double sumSt=0;
//int[] marginal1 = marginal1(d);
//int[] marginal2 = marginal2(d);
/*
double[] ncasecont = new double[d[0].length];
for(int i=0;i<ncasecont.length;i++){
ncasecont[i] = (double)marginal2[i];
}
double nh = Calculator.harmonicMean(ncasecont);
*/
/*
for(int i=0;i<ret.length;i++){
for(int j=0;j<ret[i].length;j++){
ret[i][j] = (double)d[i][j]*nh/ncasecont[j];
}
}
*/
double[][] ret = {{ad,bc},{bc,ad}};
for(int i=0;i<ret.length;i++){
for(int j=0;j<ret[i].length;j++){
sumOriginal += (double)d[i][j];
sumSt +=ret[i][j];
}
}
double ratio = sumOriginal/sumSt;
//System.out.println("ratio " + ratio);
for(int i=0;i<ret.length;i++){
for(int j=0;j<ret[i].length;j++){
ret[i][j] /=ratio;
//System.out.println("ret " + ret[i][j]);
}
}
return ret;
}
public static double[] StCaesContChiStChiFisher(int[][] d){
double[] ret = new double[5];//Chi, ChiP,stChi,stChiP,FisherP
double[][] stTable = StandardCaseCont(d);
double[][] dtable = new double[d.length][d[0].length];
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
dtable[i][j]=(double)d[i][j];
}
}
ret[0] = Chi.chi(dtable);
ret[1] = Chi2Distribution.upper(1,ret[0]);
ret[2] = Chi.chi(stTable);
ret[3] = Chi2Distribution.upper(1,ret[2]);
ret[4] = Fisher.Fishernxm2(d);
return ret;
}
public static double[] StFactorChiStChiFisher(int[][] d){
double[] ret = new double[5];//Chi, ChiP,stChi,stChiP,FisherP
double[][] stTable = StandardFactor(d);
double[][] dtable = new double[d.length][d[0].length];
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
dtable[i][j]=(double)d[i][j];
}
}
ret[0] = Chi.chi(dtable);
ret[1] = Chi2Distribution.upper(1,ret[0]);
ret[2] = Chi.chi(stTable);
ret[3] = Chi2Distribution.upper(1,ret[2]);
ret[4] = Fisher.Fishernxm2(d);
return ret;
}
public static double[] StBothChiStChiFisher(int[][] d){
double[] ret = new double[5];//Chi, ChiP,stChi,stChiP,FisherP
double[][] stTable = StandardBoth(d);
double[][] dtable = new double[d.length][d[0].length];
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
dtable[i][j]=(double)d[i][j];
}
}
ret[0] = Chi.chi(dtable);
ret[1] = Chi2Distribution.upper(1,ret[0]);
ret[2] = Chi.chi(stTable);
ret[3] = Chi2Distribution.upper(1,ret[2]);
ret[4] = Fisher.Fishernxm2(d);
return ret;
}
public static int[] marginal1(int[][] d){
int[] ret = new int[d.length];
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
ret[i] += d[i][j];
}
}
return ret;
}
public static int[] marginal2(int[][] d){
int[] ret = new int[d[0].length];
for(int i=0;i<d.length;i++){
for(int j=0;j<d[i].length;j++){
ret[j] += d[i][j];
}
}
return ret;
}}