集計
多数の因子があるとする。それらは、カテゴリカルな因子である。サンプルについて、それぞれの因子について観測されたデータが得られるとする。
何かの都合で、これらを複合カテゴリ(因子1のカテゴリがxで因子2のそれがyで・・・というのを弁別して個別のカテゴリとしたもの)ごとに集計したいとする。複数SNPのジェノタイプデータも、そのひとつ。
2分探索木を使って格納してみることにした。
リンクしているすべての関数につながっていないので、そのまま使うというわけには行かないので、主に自分のための覚書。
2分探索木に関する日記の記事は、こちらやこちら。
package binaryTree; /** * 2分探索木 * * @version $Revision: 1.6 $, $Date: 2003/04/28 23:23:14 $ */ import java.io.*; public class BinarySearchTreeRYMultiCategory { class Node { Node left, right; int id; int[] category; double count; double freq; double noderk; double LNexpvalue; double LNgeomean; Node(Node left, Node right, int id,int[] category) { this.left = left; this.right = right; this.id=id; this.category = category; this.count=1; } Node(Node left, Node right, int id,int[] category,double freq) { this.left = left; this.right = right; this.id=id; this.category = category; this.count=freq; } Node(Node left, Node right) { this.left = left; this.right = right; this.id=-99; this.category = new int[ncol]; for(int i=0;i<category.length;i++){ this.category[i]=-99; } this.count=0; } Node(Node left, Node right, int id) { this.left = left; this.right = right; this.id=id; this.category = new int[ncol]; for(int i=0;i<category.length;i++){ this.category[i]=-99; } this.count=0; } } public int ncol; final private Node zero = new Node(null, null,-999), // 各葉の子(番人用) rootParent = new Node(null, zero); // {\tt rootParent.right} が根 private Node parent; private boolean isChildLeft; // 検索成功時の親 int numNode; double N; public boolean isEmpty() { return (rootParent.right == zero); } public BinarySearchTreeRYMultiCategory(int ncol_){ ncol=ncol_; } public double r2; public double rk; public double chi2; public Node searchNode(int id_) { // 検索(未登録なら {\tt null} を返す) zero.id=-99; // {\tt zero} は番人 Node child = rootParent; //int cmp = 1; // 最初の子は {\tt rootParent.right} double cmp = 1; boolean loop=true; do { parent = child; if (cmp < 0) { child = child.left; isChildLeft = true; } else { child = child.right; isChildLeft = false; } //System.out.println("value="+value); //System.out.println("child.value="+child.value); if(child.id==-99){ loop=false; }else{ cmp=-id_+child.id; if(cmp==0){ loop=false; } } //} while ((cmp = key.compareTo(child.key)) != 0); } while (loop); //System.out.println("childvalue="+child.value); return (child == zero) ? null : child; } public Node insertNode(int id_,int[] category_) { // 挿入(登録) final Node target = searchNode(id_); if (target != null){ // すでに登録されている target.count++; return null; } Node newChild = new Node(zero, zero, id_,category_); if (isChildLeft) parent.left = newChild; else parent.right = newChild; numNode++; N++; return newChild; } public Node insertNodeWithExp(int id_,int[] category_,double exp) { // 挿入(登録) final Node target = searchNode(id_); if (target != null){ // すでに登録されている target.count++; return null; } Node newChild = new Node(zero, zero, id_,category_); newChild.LNexpvalue=exp; newChild.LNgeomean=newChild.LNexpvalue/(double)newChild.category.length; if (isChildLeft) parent.left = newChild; else parent.right = newChild; numNode++; N++; return newChild; } public Node insertNodeWithFreq(int id_,int[] category_,double freq) { // 挿入(登録) final Node target = searchNode(id_); if (target != null){ // すでに登録されている target.count+=freq; N+=freq; return null; } Node newChild = new Node(zero, zero, id_,category_,freq); if (isChildLeft) parent.left = newChild; else parent.right = newChild; numNode++; N+=freq; return newChild; } public Node insertNodeWithFreqExp(int id_,int[] category_,double freq,double exp) { // 挿入(登録) final Node target = searchNode(id_); if (target != null){ // すでに登録されている target.count+=freq; N+=freq; return null; } Node newChild = new Node(zero, zero, id_,category_,freq); newChild.LNexpvalue=exp; newChild.LNgeomean=newChild.LNexpvalue/(double)newChild.category.length; if (isChildLeft) parent.left = newChild; else parent.right = newChild; numNode++; N+=freq; return newChild; } public boolean deleteNode(int id_) { // 削除できれば {\tt true} を返す final Node target = searchNode(id_); if (target == null) return false; // 未登録 Node newChild; // {\tt target} の代わりに {\tt parent} の子になる if (target.left == zero) newChild = target.right; else if (target.right == zero) newChild = target.left; else { Node s = target.left; // {\tt s} を {\tt target} の次に小さいものに if (s.right != zero) { Node p; // {\tt s} の親 do { p = s; s = s.right; } while (s.right != zero); p.right = s.left; s.left = target.left; } s.right = target.right; newChild = s; } if (isChildLeft) parent.left = newChild; else parent.right = newChild; numNode--; N--; return true; // 削除成功, C++ では {\tt delete target;} も必要 } public boolean decreaseNode(int id_) { // 削除できれば {\tt true} を返す final Node target = searchNode(id_); if (target == null) return false; // 未登録 if (target.count>=1){ target.count--; }else{ deleteNode(id_); } return true; // 削除成功, C++ では {\tt delete target;} も必要 } public void calculate() { System.out.println("#######"); rk=-1; if (!isEmpty()) calculate(rootParent.right); } private void calculate(Node p) { // 深さ優先探索,中間順でキーを表示 if (p.left != zero) { depth++; calculate(p.left); depth--; } if (p.right != zero) { depth++; calculate(p.right); depth--; } //for (int i = 0; i < depth; i++) System.out.print("\t"); String st="ID\t"; st+=p.id+"\tdata\t"; for(int i=0;i<p.category.length;i++){ st+=p.category[i]+","; } st+="\tcount\t"; st+=p.count; st+="\tfraction\t"; p.freq=p.count/N; st+=p.freq; st+="\texpFraction\t"+Math.exp(p.LNexpvalue); double nodegeomean=Math.exp(p.LNgeomean); st+="\tGeoMean\t"+nodegeomean; p.noderk=(Math.log(p.freq)-p.LNgeomean)*(double)(p.category.length)/(double)(p.category.length-1); p.noderk=Math.exp(p.noderk); //System.out.println("plus\t"+p.noderk); rk+=p.noderk; st+="\trkPerType\t"+p.noderk; System.out.println(st); } public void printNode() { if (!isEmpty()) printNode(rootParent.right); } private int depth = 0; private void printNode(Node p) { // 深さ優先探索,中間順でキーを表示 if (p.left != zero) { depth++; printNode(p.left); depth--; } for (int i = 0; i < depth; i++) System.out.print("\t"); String st=""; st+=p.id+","; for(int i=0;i<p.category.length;i++){ st+=p.category[i]+""; } st+=","; //st+=p.count; //st+=","; double nodefreq=p.count/N; st+=nodefreq; //st+=","+Math.exp(p.LNexpvalue); double nodegeomean=Math.exp(p.LNgeomean); //st+=","+nodegeomean; double noderk=(Math.log(nodefreq)-p.LNgeomean)*(double)(p.category.length)/(double)(p.category.length-1); noderk=Math.exp(noderk); //st+=","+noderk; System.out.println(st); if (p.right != zero) { depth++; printNode(p.right); depth--; } } private void giveExpAndGeoMean(){ } public static void main(String[] args) throws IOException { int n=10; double[] data=new double[n]; for(int i=0;i<data.length;i++){ data[i]=Math.random(); } int[][] d={{0,0,0,0,0,0},{0,1,0,1,0,1},{1,1,1,1,1,1},{0,0,0,0,0,0},{1,1,1,1,1,1}}; int[] id = {0,1,2,0,2}; BinarySearchTreeRYMultiCategory tree = new BinarySearchTreeRYMultiCategory(d[0].length); /* System.out.print("命令 Iabc: abcを挿入\n" + " Dabc: abcを削除\n" + " Sabc: abcを検索\n"); */ String message; for (int i=0;i<d.length;i++) { int value=id[i]; if (tree.insertNode(value,d[i]) != null) message = "登録しました."; else message = "登録ずみです."; //break; System.out.println(message); tree.printNode(); System.out.println("numNode\t"+tree.numNode); } int[] searchID={2}; for(int i=0;i<searchID.length;i++){ if (tree.searchNode(id[searchID[i]]) != null) message = "登録されています."; else message = "登録されていません"; System.out.println(message); } int valueex=1; if (tree.searchNode(valueex) != null) message = "登録されています."; else message = "登録されていません"; System.out.println(message); int[] deleteID={0}; for(int i=0;i<deleteID.length;i++){ if (tree.deleteNode(id[deleteID[i]])) message = "削除しました."; else message = "登録されていません."; System.out.println(message); System.out.println("numNode\t"+tree.numNode); } tree.printNode(); /* for (int i=0;i<data.length;i++) { String message; double value=data[i]; String insert="'I'"; switch ('I') { case 'I': if (tree.insertNode(value) != null) message = "登録しました."; else message = "登録ずみです."; break; case 'D': if (tree.deleteNode(value)) message = "削除しました."; else message = "登録されていません."; break; case 'S': if (tree.searchNode(value) != null) message = "登録されています."; else message = "登録されていません"; break; default: message = "使えるのは I, D, S です."; break; } System.out.println(message); tree.printNode(); } */ } }
package multiSNPLD; public class MultiCategoricalChiPresentOnly { int[][] data; int nlin; int ncol; int[] ncat; double[][] colfreq; int[][][] count; int[][][] typecount; double N; double rk; binaryTree.BinarySearchTreeRYMultiCategory tr; /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ int[][] d0 ={{0,0},{0,1},{1,0},{1,1}}; int[][] d = {{0,0,0},{0,0,1},{0,1,0},{0,1,1},{1,0,0},{1,0,1},{1,1,0},{1,1,1}}; int[][] d2 ={{0,0,0,0,0,0},{1,1,1,1,1,1},{0,0,0,0,0,1}}; int[][] d3 ={ {0,0,0,0,0,0}, {1,1,1,1,1,1}, {0,0,0,1,1,1}, {0,0,1,1,1,1}, {0,1,1,1,1,1}, {0,0,0,0,1,1}, {0,0,0,0,0,1}, {1,1,1,1,1,2}, {1,1,1,1,2,2}, {1,1,1,2,2,2}, {1,1,2,2,2,2}, {1,2,2,2,2,2}, {0,0,0,0,0,1}, {0,0,0,0,1,1}, {0,0,0,1,1,1}, {0,0,1,1,1,1}, {0,1,1,1,1,1}, {2,2,2,2,2,2}, }; double[] freq=new double[d0.length]; for(int i=0;i<freq.length;i++){ freq[i]=Math.random(); } StatUtilsZ.MiscUtilX.standard(freq); MultiCategoricalChiPresentOnly mc=new MultiCategoricalChiPresentOnly(d0); for(int i=0;i<mc.colfreq.length;i++){ for(int j=0;j<mc.colfreq[i].length;j++){ System.out.print(mc.colfreq[i][j]+"\t"); } System.out.println(); } System.out.println("mc\t"+mc.tr.rk); System.out.println("============"); MultiCategoricalChiPresentOnly mc2=new MultiCategoricalChiPresentOnly(d0,freq); for(int i=0;i<mc.colfreq.length;i++){ for(int j=0;j<mc.colfreq[i].length;j++){ System.out.print(mc.colfreq[i][j]+"\t"); } System.out.println(); } System.out.println("mc2\t"+mc2.tr.rk); /* for(int i=0;i<mc.count.length;i++){ if(mc.count[i][mc.ncol][0]!=0){ for(int j=0;j<mc.count[i].length;j++){ for(int k=0;k<mc.count[i][j].length;k++){ System.out.print(mc.count[i][j][k]); } } System.out.println(); } } System.out.println("rk\t"+mc.rk); System.out.println("chik\t"+mc.chik); */ } public MultiCategoricalChiPresentOnly(int[][] d){ data=StatUtilsZ.MiscUtilX.DeepCopyInt2(d); tr = new binaryTree.BinarySearchTreeRYMultiCategory(d[0].length); nlin=data.length; ncol=data[0].length; int[] colmin=new int[ncol]; int[] colmax=new int[ncol]; //int[][] count=new int[ncol+1][1]; N=data.length; //int nummultcat=1; for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ if(i==0){ colmin[j]=data[i][j]; colmax[j]=data[i][j]; }else{ if(colmin[j]>data[i][j]){ colmin[j]=data[i][j]; } if(colmax[j]<data[i][j]){ colmax[j]=data[i][j]; } } } } colfreq=new double[ncol][0]; for(int i=0;i<colfreq.length;i++){ colfreq[i]=new double[colmax[i]-colmin[i]+1]; //nummultcat*=colfreq[i].length; } //System.out.println("nummultcat "+nummultcat); //count=new int[nummultcat][ncol+1][1]; int[] kurai=new int[ncol]; kurai[0]=1; for(int i=1;i<kurai.length;i++){ kurai[i]=kurai[i-1]*(colmax[i-1]-colmin[i-1]+1); //System.out.println("kurai "+kurai[i]); } int[][] multtype=new int[data.length][ncol]; int[] id = new int[data.length]; for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ colfreq[j][data[i][j]-colmin[j]]++; multtype[i][j]=data[i][j]-colmin[j]; } int serial=0; for(int j=0;j<multtype[i].length;j++){ //System.out.println("kurai[j]*multtype[j] "+kurai[j]*multtype[j]); serial+=kurai[j]*multtype[i][j]; } id[i]=serial; /* //if(count[serial][ncol+1][0]==0){ //System.out.println("serial "+serial); for(int j=0;j<count[serial].length-1;j++){ count[serial][j][0]=multtype[j]; } //} count[serial][ncol][0]++; */ } for(int i=0;i<data.length;i++){ double Lnexp=0; for(int j=0;j<multtype[i].length;j++){ double tmp = colfreq[j][multtype[i][j]]/(double)N; System.out.println("tmp=\t"+tmp); Lnexp+=Math.log((double)colfreq[j][multtype[i][j]]/(double)N); } tr.insertNodeWithExp(id[i], data[i],Lnexp); //System.out.println("-------------"); //tr.printNode(); } tr.printNode(); System.out.println("-------------"); tr.calculate(); /* rk=-1;chik=0; double k=1.0/(double)(ncol-1); for(int i=0;i<count.length;i++){ if(count[i][ncol][0]!=0){ double elem = (1+k)*Math.log((double)count[i][ncol][0]/(double)N); for(int j=0;j<count[i].length-1;j++){ elem-=k*Math.log((double)colfreq[j][count[i][j][0]]/(double)N); } rk+=Math.exp(elem); } } chik=rk*N; */ } public MultiCategoricalChiPresentOnly(int[][] d,double[] freq){ data=StatUtilsZ.MiscUtilX.DeepCopyInt2(d); tr = new binaryTree.BinarySearchTreeRYMultiCategory(d[0].length); nlin=data.length; ncol=data[0].length; int[] colmin=new int[ncol]; int[] colmax=new int[ncol]; //int[][] count=new int[ncol+1][1]; for(int i=0;i<freq.length;i++){ N+=freq[i]; } //System.out.println("N="+N); //N=data.length; //int nummultcat=1; for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ if(i==0){ colmin[j]=data[i][j]; colmax[j]=data[i][j]; }else{ if(colmin[j]>data[i][j]){ colmin[j]=data[i][j]; } if(colmax[j]<data[i][j]){ colmax[j]=data[i][j]; } } } } colfreq=new double[ncol][0]; for(int i=0;i<colfreq.length;i++){ colfreq[i]=new double[colmax[i]-colmin[i]+1]; //nummultcat*=colfreq[i].length; } //System.out.println("nummultcat "+nummultcat); //count=new int[nummultcat][ncol+1][1]; int[] kurai=new int[ncol]; kurai[0]=1; for(int i=1;i<kurai.length;i++){ kurai[i]=kurai[i-1]*(colmax[i-1]-colmin[i-1]+1); //System.out.println("kurai "+kurai[i]); } int[][] multtype=new int[data.length][ncol]; int[] id = new int[data.length]; for(int i=0;i<data.length;i++){ for(int j=0;j<data[i].length;j++){ colfreq[j][data[i][j]-colmin[j]]+=freq[i]; multtype[i][j]=data[i][j]-colmin[j]; } int serial=0; for(int j=0;j<multtype[i].length;j++){ //System.out.println("kurai[j]*multtype[j] "+kurai[j]*multtype[j]); serial+=kurai[j]*multtype[i][j]; } id[i]=serial; /* //if(count[serial][ncol+1][0]==0){ //System.out.println("serial "+serial); for(int j=0;j<count[serial].length-1;j++){ count[serial][j][0]=multtype[j]; } //} count[serial][ncol][0]++; */ } for(int i=0;i<data.length;i++){ double Lnexp=0; for(int j=0;j<multtype[i].length;j++){ double tmp = colfreq[j][multtype[i][j]]/(double)N; //System.out.println("tmp=\t"+tmp); Lnexp+=Math.log((double)colfreq[j][multtype[i][j]]/(double)N); } tr.insertNodeWithFreqExp(id[i], data[i],freq[i],Lnexp); //System.out.println("-------------"); //tr.printNode(); } tr.printNode(); System.out.println("-------------"); tr.calculate(); /* rk=-1;chik=0; double k=1.0/(double)(ncol-1); for(int i=0;i<count.length;i++){ if(count[i][ncol][0]!=0){ double elem = (1+k)*Math.log((double)count[i][ncol][0]/(double)N); for(int j=0;j<count[i].length-1;j++){ elem-=k*Math.log((double)colfreq[j][count[i][j][0]]/(double)N); } rk+=Math.exp(elem); } } chik=rk*N; */ } }