001package org.opengion.penguin.math.statistics;
002
003import org.apache.commons.math3.linear.MatrixUtils;
004import org.apache.commons.math3.linear.RealMatrix;
005import org.apache.commons.math3.stat.correlation.PearsonsCorrelation;
006
007/**
008 * apache.commons.mathを利用した相関計算及びその周辺機能を利用するためのクラスです。
009 * 
010 * とりあえず通常のピアソン積率相関のみを利用可能としておきます。
011 * 
012 */
013public class HybsCorrelation {
014        private String[] names;
015        private double[][] pearsonsMatrix;
016        private RealMatrix corrMatrix;
017        
018                
019        /**
020         * コンストラクタ。
021         * 与えたデータマトリクスを元にピアソン積率相関を計算します。
022         * 名称 = { "数学" , "英語", "国語" }
023         * データ = { { 90 ,60 ,70 }, {70, 90, 80 } }
024         * のような形としてデータを与えます。
025         * @param name ラベル
026         * @param matrix 値のデータ
027         */
028        public HybsCorrelation(String[] name, double[][] matrix){
029                // 一応元データをセットしておく
030                this.names = name;
031                this.pearsonsMatrix = matrix;
032                
033                // ここで相関係数行列を作成してしまう
034                corrMatrix = (new PearsonsCorrelation()).computeCorrelationMatrix(pearsonsMatrix);
035        }
036        
037        /**
038         * コンストラクタ。
039         * 計算後の相関係数行列をdouble[][]型で直接与えられるようにしておきます。
040         * 以前に計算した行列を使って行列の積を算出する場合に利用します。
041         * 
042         * @param matrix 相関係数行列
043         */
044        public HybsCorrelation( double[][] matrix){
045                corrMatrix = MatrixUtils.createRealMatrix( matrix );
046        }
047        
048        /**
049         * コンストラクタで算出した相関値行列に対して与えた行列を掛け算します。
050         * 例えば以下のような算出を行う事が可能です。
051         * 各商品を何回購入したかというデータを人数分用意し、相関係数行列を作成し、
052         *  それに対してある人の今まで購入した履歴を掛け算する事で相関の高い商品を導出します。
053         *  つまり、購入した事のないもので有意な相関係数を持つものは購入可能性が高いと言えます。
054         * @param data 掛け算する行列
055         * @return 行列積の結果マトリクス
056         */
057        public double[][] multiply(double[][] data){
058                RealMatrix dataMatrix = MatrixUtils.createRealMatrix(data);
059            RealMatrix scores = dataMatrix.multiply(corrMatrix);
060                
061                return scores.getData();
062        }
063        
064        /**
065         * 相関値行列取得。
066         * @return 相関マトリクス
067         */
068        public double[][] getCorrMatrix(){
069                return corrMatrix.getData();
070        }
071        
072        /**
073         * 指定行の相関値配列取得。
074         * @param x ROW番号
075         * @return 行方向の相関ベクトル
076         */
077        public double[] getCorrMatrixRow(int x){
078                return corrMatrix.getRow(x);
079        }
080        
081        /**
082         * 指定列の相関値配列取得。
083         * @param x COL番号
084         * @return 列方向の相関ベクトル
085         */
086        public double[] getCorrMatrixCol(int x){
087                return corrMatrix.getColumn(x);
088        }
089        
090        /**
091         * 名称配列の取得。
092         * @return 名称配列
093         */
094        public String[] getNames(){
095                return names;
096        }
097        
098        /**
099         * 名称配列のセット。
100         * @param name 名称配列
101         */
102        public void setNames( String[] name){
103                this.names = name;
104        }
105
106        /*** ここまでが本体 ***/
107        /*** ここからテスト用mainメソッド ***/
108        /**
109         * @param args *****************************************/
110        public static void main(final String [] args) {
111                String[] name = {"A", "B", "C", "D","E"};
112            double[][] data = {
113              {3, 1, 0, 0 , 1},
114              {1, 0, 0, 0 , 1},
115              {0, 0, 2, 2 , 2},
116              {2, 2, 1, 0 , 0},
117              {1, 0, 2, 4 , 1},
118            };
119                
120                HybsCorrelation rtn = new HybsCorrelation(name,data);
121                
122                for( int i = 0; i< rtn.getCorrMatrix().length; i++ ){
123                        System.out.println(java.util.Arrays.toString(rtn.getCorrMatrix()[i]));
124                }
125                
126                // オススメ度計算
127                System.out.println(java.util.Arrays.toString(rtn.multiply( new double[][] { {0, 1, 0, 0 , 0}})[0]));
128                
129        }
130}
131