多次元度数分布
通常の度数分布(尺度がひとつ)の度数分布をさらさらと標準出力で描きたいことはよくある。さらに、多次元のdouble型データから、次元別に件数をカウントしたいこともある。"DiscreteMathTools.Tensor"はこちら。
2次元尺度の度数をプロットするには、3次元プロットが必要。それに関する記事はこちら
package StatUtils;
import java.io.*;
public class Histogram {/**
* @param args
*/
int degree;
double[][] data;
int[] kizami;
DiscreteMathTools.Tensor count;
double[] max;
double[] min;
double[][][] scale;
double[] width;
public static void main(String[] args)throws Exception {
String infile = "ThreeD2.txt";
double[][] data = BioBankPerm.InOut4.readDatFileIOStringTAB(infile);
// TODO 自動生成されたメソッド・スタブ
//double[][] data = {{1,2,3},{1,3,4},{2,5,4},{4,3,2}};
int[] kizami = {10,10};
Histogram h = new Histogram(data,kizami);
Histogram.PrintHistogram(h,"\t","\n");
Histogram.PrintHistogram2D(h, 0,1,2,"\t","\n");}
/*
* 多次元ヒストグラム関数
* k次元データがk列xnレコード行であるときに、
* kizami[] (長さkのベクター)情報を基に各区画(\Pi(kizami[j])
* の要素数をカウントする
*/
public Histogram(double[][] data_,int[] kizami_){
data = MiscUtil.DeepCopyDouble2(data_);
double[][] datatateyoko=DiscreteMathTools.MatrixExec.Transversmat(data);
degree = data[0].length;
kizami = MiscUtil.DeepCopyInt1(kizami_);
int numcell = 1;
for(int i=0;i<kizami.length;i++){
numcell *= kizami[i];
}
double[] vacantdata = new double[numcell];
for(int i=0;i<vacantdata.length;i++){
vacantdata[i]=0;
}
count = new DiscreteMathTools.Tensor(degree,kizami,vacantdata);
max = new double[degree];
min = new double[degree];
width = new double[degree];
scale = new double[degree][][];
for(int i=0;i<degree;i++){
scale[i]= new double[kizami[i]][2];
}
for(int i=0;i<degree;i++){
max[i] = StatUtils.Calculator.max(datatateyoko[i]);
min[i] = StatUtils.Calculator.min(datatateyoko[i]);
}
for(int i=0;i<degree;i++){
width[i] = (max[i]-min[i])/(double)kizami[i];
}
for(int i=0;i<degree;i++){
for(int j=0;j<kizami[i];j++){
if(j==0){
scale[i][0][0]=min[i];
scale[i][0][1]=min[i]+width[i];
}else{
scale[i][j][0]=scale[i][j-1][1];
scale[i][j][1]=scale[i][j-1][1]+width[i];
}
}
}
for(int i=0;i<data.length;i++){
int[] tmp = new int[degree];
for(int j=0;j<data[i].length;j++){
tmp[j] = (int)(kizami[j]*(data[i][j]-min[j])/(max[j]-min[j]));
//System.out.println("tmp " + tmp);
if(tmp[j]==kizami[j]){
tmp[j]--;
}
}
DiscreteMathTools.Tensor.AddElem(count,tmp,1);
}
}
public static void PrintHistogram(Histogram h,String sep1,String sep2){
String ret = StringHistogram(h,sep1,sep2);
System.out.println(ret);
}
public static double[][] DoubleHistogram2D(Histogram h, int x,int y,int v,String sep1,String sep2){
double[][] ret = new double[h.kizami[x]][h.kizami[y]];
for(int i=0;i<h.count.data.length;i++){
int tmpx = h.count.index[i][x];
int tmpy = h.count.index[i][y];
ret[tmpx][tmpy]+=h.count.data[i];
}
return ret;
}
public static void PrintHistogram2D(Histogram h,int x, int y, int v,String sep1,String sep2){
double[][] ret = DoubleHistogram2D(h,x,y,v,sep1,sep2);
DiscreteMathTools.MatrixExec.PrintMat(ret,sep1,sep2);
}
public static String StringHistogram(Histogram h,String sep1,String sep2){
String ret ="";
ret += "degree" + sep1 + h.degree + sep2;
ret += "kizami" + sep1;
for(int i=0;i<h.degree;i++){
ret += h.kizami[i] + sep1;
}
ret += sep2;
ret += "min" + sep1;
for(int i=0;i<h.degree;i++){
ret += h.min[i]+sep1;
}
ret += sep2;
ret += "max" + sep1;
for(int i=0;i<h.degree;i++){
ret += h.max[i]+sep1;
}
ret += sep2;
ret += h.count.StringTensor(h.count,sep1,sep2);
/*
for(int i=0;i<h.count.length;i++){
for(int j=0;j<h.count[i].length;j++){
ret += j + sep1;
}
ret += sep2;
}
*/
return ret;
}
/*
* PermHistのときに作成した1次元データのヒストグラム用関数
*/
public static int[] hist(double[] d,int segnum){
int[] ret = new int[segnum];
for(int i=0;i<ret.length;i++){
ret[i]=0;
}
double max = d[0];
double min = d[0];
for(int i=1;i<d.length;i++){
if(max<d[i]){
max=d[i];
}
if(min>d[i]){
min=d[i];
}
}
double wid = (max-min)/(double)segnum;
for(int i=0;i<d.length;i++){
int tmp = (int)(segnum*(d[i]-min)/(max-min));
//System.out.println("tmp " + tmp);
if(tmp==segnum){
tmp--;
}
ret[tmp]++;
}
//System.out.println("max min " + max + " " + min);
return ret;
}
public static double[][] histAccum(double[] d,int segnum){
double[][] ret = new double[4][segnum];
for(int i=0;i<ret[0].length;i++){
ret[0][i]=0;
ret[1][i]=0;
}
double max = d[0];
double min = d[0];
for(int i=1;i<d.length;i++){
if(max<d[i]){
max=d[i];
}
if(min>d[i]){
min=d[i];
}
}
double wid = (max-min)/(double)segnum;
for(int i=0;i<segnum;i++){
ret[2][i]=min + wid*i;
ret[3][i]=min + wid*(i+1);
}
ret[3][ret[3].length-1]=max;
for(int i=0;i<d.length;i++){
int tmp = (int)(segnum*(d[i]-min)/(max-min));
//System.out.println("tmp " + tmp);
if(tmp==segnum){
tmp--;
}
ret[0][tmp]++;
}
ret[1][0]=ret[0][0];
for(int i=1;i<ret[0].length;i++){
ret[1][i]=ret[1][i-1]+ret[0][i];
}
//System.out.println("max min " + max + " " + min);
return ret;
}
public static String StringHist(int[] d,int scale){
String ret="";
for(int i=0;i<d.length;i++){
ret += "\t|";
for(int j=0;j<d[i]/scale;j++){
ret += "*";
}
ret += "\n";
}
return ret;
}
public static void PrintHist(int[] d,int scale){
String ret = StringHist(d,scale);
System.out.println(ret);
}}