    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 );              // 6.9.7.0 (2018/05/14) PMD Useless parentheses.
    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}