Covariance.java
- /*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- /*
- * This is not the original file distributed by the Apache Software Foundation
- * It has been modified by the Hipparchus project
- */
- package org.hipparchus.stat.correlation;
- import org.hipparchus.exception.LocalizedCoreFormats;
- import org.hipparchus.exception.MathIllegalArgumentException;
- import org.hipparchus.linear.BlockRealMatrix;
- import org.hipparchus.linear.RealMatrix;
- import org.hipparchus.stat.descriptive.moment.Mean;
- import org.hipparchus.stat.descriptive.moment.Variance;
- /**
- * Computes covariances for pairs of arrays or columns of a matrix.
- * <p>
- * The constructors that take {@code RealMatrix} or {@code double[][]}
- * arguments generate covariance matrices. The columns of the input
- * matrices are assumed to represent variable values.
- * <p>
- * The constructor argument {@code biasCorrected} determines whether or
- * not computed covariances are bias-corrected.
- * <p>
- * Unbiased covariances are given by the formula:
- * <p>
- * <code>cov(X, Y) = Σ[(x<sub>i</sub> - E(X))(y<sub>i</sub> - E(Y))] / (n - 1)</code>
- * <p>
- * where {@code E(X)} is the mean of {@code X} and {@code E(Y)}
- * is the mean of the <code>Y</code> values.
- * <p>
- * Non-bias-corrected estimates use {@code n} in place of {@code n - 1}.
- */
- public class Covariance {
- /** The covariance matrix. */
- private final RealMatrix covarianceMatrix;
- /** Number of observations (length of covariate vectors). */
- private final int n;
- /**
- * Create a Covariance with no data.
- */
- public Covariance() {
- super();
- covarianceMatrix = null;
- n = 0;
- }
- /**
- * Create a Covariance matrix from a rectangular array
- * whose columns represent covariates.
- * <p>
- * The <code>biasCorrected</code> parameter determines whether or not
- * covariance estimates are bias-corrected.
- * <p>
- * The input array must be rectangular with at least one column
- * and two rows.
- *
- * @param data rectangular array with columns representing covariates
- * @param biasCorrected true means covariances are bias-corrected
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least two rows and one column.
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least one row and one column.
- */
- public Covariance(double[][] data, boolean biasCorrected)
- throws MathIllegalArgumentException {
- this(new BlockRealMatrix(data), biasCorrected);
- }
- /**
- * Create a Covariance matrix from a rectangular array
- * whose columns represent covariates.
- * <p>
- * The input array must be rectangular with at least one column
- * and two rows.
- *
- * @param data rectangular array with columns representing covariates
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least two rows and one column.
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least one row and one column.
- */
- public Covariance(double[][] data) throws MathIllegalArgumentException {
- this(data, true);
- }
- /**
- * Create a covariance matrix from a matrix whose columns
- * represent covariates.
- * <p>
- * The <code>biasCorrected</code> parameter determines whether or not
- * covariance estimates are bias-corrected.
- * <p>
- * The matrix must have at least one column and two rows.
- *
- * @param matrix matrix with columns representing covariates
- * @param biasCorrected true means covariances are bias-corrected
- * @throws MathIllegalArgumentException if the input matrix does not have
- * at least two rows and one column
- */
- public Covariance(RealMatrix matrix, boolean biasCorrected)
- throws MathIllegalArgumentException {
- checkSufficientData(matrix);
- n = matrix.getRowDimension();
- covarianceMatrix = computeCovarianceMatrix(matrix, biasCorrected);
- }
- /**
- * Create a covariance matrix from a matrix whose columns
- * represent covariates.
- * <p>
- * The matrix must have at least one column and two rows.
- *
- * @param matrix matrix with columns representing covariates
- * @throws MathIllegalArgumentException if the input matrix does not have
- * at least two rows and one column
- */
- public Covariance(RealMatrix matrix) throws MathIllegalArgumentException {
- this(matrix, true);
- }
- /**
- * Returns the covariance matrix
- *
- * @return covariance matrix
- */
- public RealMatrix getCovarianceMatrix() {
- return covarianceMatrix;
- }
- /**
- * Returns the number of observations (length of covariate vectors)
- *
- * @return number of observations
- */
- public int getN() {
- return n;
- }
- /**
- * Compute a covariance matrix from a matrix whose columns represent covariates.
- *
- * @param matrix input matrix (must have at least one column and two rows)
- * @param biasCorrected determines whether or not covariance estimates are bias-corrected
- * @return covariance matrix
- * @throws MathIllegalArgumentException if the matrix does not contain sufficient data
- */
- protected RealMatrix computeCovarianceMatrix(RealMatrix matrix, boolean biasCorrected)
- throws MathIllegalArgumentException {
- int dimension = matrix.getColumnDimension();
- Variance variance = new Variance(biasCorrected);
- RealMatrix outMatrix = new BlockRealMatrix(dimension, dimension);
- for (int i = 0; i < dimension; i++) {
- for (int j = 0; j < i; j++) {
- double cov = covariance(matrix.getColumn(i), matrix.getColumn(j), biasCorrected);
- outMatrix.setEntry(i, j, cov);
- outMatrix.setEntry(j, i, cov);
- }
- outMatrix.setEntry(i, i, variance.evaluate(matrix.getColumn(i)));
- }
- return outMatrix;
- }
- /**
- * Create a covariance matrix from a matrix whose columns represent
- * covariates. Covariances are computed using the bias-corrected formula.
- *
- * @param matrix input matrix (must have at least one column and two rows)
- * @return covariance matrix
- * @throws MathIllegalArgumentException if matrix does not contain sufficient data
- * @see #Covariance
- */
- protected RealMatrix computeCovarianceMatrix(RealMatrix matrix)
- throws MathIllegalArgumentException {
- return computeCovarianceMatrix(matrix, true);
- }
- /**
- * Compute a covariance matrix from a rectangular array whose columns represent covariates.
- *
- * @param data input array (must have at least one column and two rows)
- * @param biasCorrected determines whether or not covariance estimates are bias-corrected
- * @return covariance matrix
- * @throws MathIllegalArgumentException if the data array does not contain sufficient data
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least one row and one column.
- */
- protected RealMatrix computeCovarianceMatrix(double[][] data, boolean biasCorrected)
- throws MathIllegalArgumentException {
- return computeCovarianceMatrix(new BlockRealMatrix(data), biasCorrected);
- }
- /**
- * Create a covariance matrix from a rectangular array whose columns represent
- * covariates. Covariances are computed using the bias-corrected formula.
- *
- * @param data input array (must have at least one column and two rows)
- * @return covariance matrix
- * @throws MathIllegalArgumentException if the data array does not contain sufficient data
- * @throws MathIllegalArgumentException if the input data array is not
- * rectangular with at least one row and one column.
- * @see #Covariance
- */
- protected RealMatrix computeCovarianceMatrix(double[][] data)
- throws MathIllegalArgumentException {
- return computeCovarianceMatrix(data, true);
- }
- /**
- * Computes the covariance between the two arrays.
- * <p>
- * Array lengths must match and the common length must be at least 2.
- *
- * @param xArray first data array
- * @param yArray second data array
- * @param biasCorrected if true, returned value will be bias-corrected
- * @return returns the covariance for the two arrays
- * @throws MathIllegalArgumentException if the arrays lengths do not match or
- * there is insufficient data
- */
- public double covariance(final double[] xArray, final double[] yArray, boolean biasCorrected)
- throws MathIllegalArgumentException {
- Mean mean = new Mean();
- double result = 0d;
- int length = xArray.length;
- if (length != yArray.length) {
- throw new MathIllegalArgumentException(
- LocalizedCoreFormats.DIMENSIONS_MISMATCH, length, yArray.length);
- } else if (length < 2) {
- throw new MathIllegalArgumentException(
- LocalizedCoreFormats.INSUFFICIENT_OBSERVED_POINTS_IN_SAMPLE, length, 2);
- } else {
- double xMean = mean.evaluate(xArray);
- double yMean = mean.evaluate(yArray);
- for (int i = 0; i < length; i++) {
- double xDev = xArray[i] - xMean;
- double yDev = yArray[i] - yMean;
- result += (xDev * yDev - result) / (i + 1);
- }
- }
- return biasCorrected ? result * ((double) length / (double)(length - 1)) : result;
- }
- /**
- * Computes the covariance between the two arrays, using the bias-corrected
- * formula.
- * <p>
- * Array lengths must match and the common length must be at least 2.
- *
- * @param xArray first data array
- * @param yArray second data array
- * @return returns the covariance for the two arrays
- * @throws MathIllegalArgumentException if the arrays lengths do not match or
- * there is insufficient data
- */
- public double covariance(final double[] xArray, final double[] yArray)
- throws MathIllegalArgumentException {
- return covariance(xArray, yArray, true);
- }
- /**
- * Throws MathIllegalArgumentException if the matrix does not have at least
- * one column and two rows.
- *
- * @param matrix matrix to check
- * @throws MathIllegalArgumentException if the matrix does not contain sufficient data
- * to compute covariance
- */
- private void checkSufficientData(final RealMatrix matrix) throws MathIllegalArgumentException {
- int nRows = matrix.getRowDimension();
- int nCols = matrix.getColumnDimension();
- if (nRows < 2 || nCols < 1) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.INSUFFICIENT_ROWS_AND_COLUMNS,
- nRows, nCols);
- }
- }
- }