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