/*******************************************************************************
* Copyright (c) 2011 epyx SA.
*
* This program is free software: you can redistribute it and/or modify it under
* the terms of the GNU Affero General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
* details.
*
* You should have received a copy of the GNU Affero General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package ch.windmobile.server.datasourcemodel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class LinearRegression {
private final Logger log = LoggerFactory.getLogger(getClass());
// Input values
private double[][] xyValues;
double[] x, y;
double sumx, sumy, sumx2;
int n;
double xbar, ybar;
double xxbar, yybar, xybar;
// Results
private double beta0;
private double beta1;
public LinearRegression(double[][] xyValues) {
this.xyValues = xyValues;
}
public void compute() {
x = new double[xyValues.length];
y = new double[xyValues.length];
// first pass: read in data, compute xbar and ybar
sumx = sumy = sumx2 = 0.0;
for (n = 0; n < xyValues.length; n++) {
x[n] = xyValues[n][0];
y[n] = xyValues[n][1];
sumx += x[n];
sumx2 += x[n] * x[n];
sumy += y[n];
}
xbar = sumx / n;
ybar = sumy / n;
// second pass: compute summary statistics
xxbar = yybar = xybar = 0.0;
for (int i = 0; i < n; i++) {
xxbar += (x[i] - xbar) * (x[i] - xbar);
yybar += (y[i] - ybar) * (y[i] - ybar);
xybar += (x[i] - xbar) * (y[i] - ybar);
}
beta1 = xybar / xxbar;
beta0 = ybar - beta1 * xbar;
// print results
log.debug("y = " + beta1 + " * x + " + beta0);
}
// analyze results
public void analyse() {
int df = n - 2;
double rss = 0.0; // residual sum of squares
double ssr = 0.0; // regression sum of squares
for (int i = 0; i < n; i++) {
double fit = beta1 * x[i] + beta0;
rss += (fit - y[i]) * (fit - y[i]);
ssr += (fit - ybar) * (fit - ybar);
}
double R2 = ssr / yybar;
double svar = rss / df;
double svar1 = svar / xxbar;
double svar0 = svar / n + xbar * xbar * svar1;
log.info("R^2 = " + R2);
log.info("std error of beta_1 = " + Math.sqrt(svar1));
log.info("std error of beta_0 = " + Math.sqrt(svar0));
svar0 = svar * sumx2 / (n * xxbar);
log.info("std error of beta_0 = " + Math.sqrt(svar0));
log.info("SSTO = " + yybar);
log.info("SSE = " + rss);
log.info("SSR = " + ssr);
}
public double getBeta0() {
return beta0;
}
public double getBeta1() {
return beta1;
}
}