package com.compomics.util.math.statistics.linear_regression.regressions;
import com.compomics.util.math.BasicMathFunctions;
import com.compomics.util.math.statistics.linear_regression.RegressionStatistics;
import java.util.ArrayList;
/**
* Performs a simple linear regression.
* TODO: replace with the Apache implementation
*
* @author Marc Vaudel
*/
public class SimpleLinearRegression {
/**
* Returns a simple linear regression. Note: r calculation is not
* implemented.
*
* @param x the x series
* @param y the y series
*
* @return a simple linear regression
*/
public static RegressionStatistics getLinearRegression(ArrayList<Double> x, ArrayList<Double> y) {
if (x == null) {
throw new IllegalArgumentException("null given as x for linear regression.");
}
if (y == null) {
throw new IllegalArgumentException("null given as y for linear regression.");
}
if (x.size() != y.size()) {
throw new IllegalArgumentException("Attempting to perform linear regression of lists of different sizes.");
}
int n = x.size();
if (n <= 1) {
throw new IllegalArgumentException("Attempting to perform linear regression of a vectore of size " + n + ".");
}
Double sumXY = 0.0;
Double sumX = 0.0;
Double sumX2 = 0.0;
Double sumY = 0.0;
Double x0 = x.get(0);
boolean newX = false;
for (int i = 0; i < n; i++) {
Double xi = x.get(i);
if (!newX && !xi.equals(x0)) {
newX = true;
}
Double yi = y.get(i);
sumXY += (xi * yi);
sumX += xi;
sumX2 += (xi * xi);
sumY += yi;
}
if (!newX) {
throw new IllegalArgumentException("Attempting to perform the linear regression of a vertical line or a point.");
}
Double xMean = sumX / n;
Double yMean = sumY / n;
Double a = (sumXY - (xMean * sumY)) / (sumX2 - (sumX * sumX / n));
Double b = yMean - (a * xMean);
Double ssTot = 0.0;
Double ssRes = 0.0;
ArrayList<Double> deltasSquare = new ArrayList<Double>(x.size());
for (int i = 0; i < x.size(); i++) {
Double xi = x.get(i);
Double yi = y.get(i);
Double fi = (a * xi) + b;
Double diffY = yi - yMean;
ssTot += (diffY * diffY);
Double diffF = yi - fi;
ssRes += (diffF * diffF);
Double deltaY = yi - b;
Double ai = deltaY / xi;
Double deltaA = ai - a;
Double deltaSquare = (xi * xi) + (deltaY * deltaY);
deltaSquare *= deltaA * deltaA;
deltaSquare /= (1 + (ai * ai));
deltaSquare /= (1 + (a * a));
deltasSquare.add(deltaSquare);
}
Double rSquared = 1.0;
if (ssTot > 0) {
rSquared = 1 - (ssRes / ssTot);
}
Double meanDelta = BasicMathFunctions.mean(deltasSquare);
Double medianDelta = BasicMathFunctions.median(deltasSquare);
return new RegressionStatistics(a, b, rSquared, meanDelta, medianDelta);
}
}