001/* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2008, by Object Refinery Limited and Contributors.
006 *
007 * Project Info:  http://www.jfree.org/jfreechart/index.html
008 *
009 * This library is free software; you can redistribute it and/or modify it
010 * under the terms of the GNU Lesser General Public License as published by
011 * the Free Software Foundation; either version 2.1 of the License, or
012 * (at your option) any later version.
013 *
014 * This library is distributed in the hope that it will be useful, but
015 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
016 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
017 * License for more details.
018 *
019 * You should have received a copy of the GNU Lesser General Public
020 * License along with this library; if not, write to the Free Software
021 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
022 * USA.
023 *
024 * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
025 * in the United States and other countries.]
026 *
027 * ---------------
028 * Regression.java
029 * ---------------
030 * (C) Copyright 2002-2008, by Object Refinery Limited.
031 *
032 * Original Author:  David Gilbert (for Object Refinery Limited);
033 * Contributor(s):   -;
034 *
035 * Changes
036 * -------
037 * 30-Sep-2002 : Version 1 (DG);
038 * 18-Aug-2003 : Added 'abstract' (DG);
039 * 15-Jul-2004 : Switched getX() with getXValue() and getY() with
040 *               getYValue() (DG);
041 *
042 */
043
044package org.jfree.data.statistics;
045
046import org.jfree.data.xy.XYDataset;
047
048/**
049 * A utility class for fitting regression curves to data.
050 */
051public abstract class Regression {
052
053    /**
054     * Returns the parameters 'a' and 'b' for an equation y = a + bx, fitted to
055     * the data using ordinary least squares regression.  The result is
056     * returned as a double[], where result[0] --> a, and result[1] --> b.
057     *
058     * @param data  the data.
059     *
060     * @return The parameters.
061     */
062    public static double[] getOLSRegression(double[][] data) {
063
064        int n = data.length;
065        if (n < 2) {
066            throw new IllegalArgumentException("Not enough data.");
067        }
068
069        double sumX = 0;
070        double sumY = 0;
071        double sumXX = 0;
072        double sumXY = 0;
073        for (int i = 0; i < n; i++) {
074            double x = data[i][0];
075            double y = data[i][1];
076            sumX += x;
077            sumY += y;
078            double xx = x * x;
079            sumXX += xx;
080            double xy = x * y;
081            sumXY += xy;
082        }
083        double sxx = sumXX - (sumX * sumX) / n;
084        double sxy = sumXY - (sumX * sumY) / n;
085        double xbar = sumX / n;
086        double ybar = sumY / n;
087
088        double[] result = new double[2];
089        result[1] = sxy / sxx;
090        result[0] = ybar - result[1] * xbar;
091
092        return result;
093
094    }
095
096    /**
097     * Returns the parameters 'a' and 'b' for an equation y = a + bx, fitted to
098     * the data using ordinary least squares regression. The result is returned
099     * as a double[], where result[0] --> a, and result[1] --> b.
100     *
101     * @param data  the data.
102     * @param series  the series (zero-based index).
103     *
104     * @return The parameters.
105     */
106    public static double[] getOLSRegression(XYDataset data, int series) {
107
108        int n = data.getItemCount(series);
109        if (n < 2) {
110            throw new IllegalArgumentException("Not enough data.");
111        }
112
113        double sumX = 0;
114        double sumY = 0;
115        double sumXX = 0;
116        double sumXY = 0;
117        for (int i = 0; i < n; i++) {
118            double x = data.getXValue(series, i);
119            double y = data.getYValue(series, i);
120            sumX += x;
121            sumY += y;
122            double xx = x * x;
123            sumXX += xx;
124            double xy = x * y;
125            sumXY += xy;
126        }
127        double sxx = sumXX - (sumX * sumX) / n;
128        double sxy = sumXY - (sumX * sumY) / n;
129        double xbar = sumX / n;
130        double ybar = sumY / n;
131
132        double[] result = new double[2];
133        result[1] = sxy / sxx;
134        result[0] = ybar - result[1] * xbar;
135
136        return result;
137
138    }
139
140    /**
141     * Returns the parameters 'a' and 'b' for an equation y = ax^b, fitted to
142     * the data using a power regression equation.  The result is returned as
143     * an array, where double[0] --> a, and double[1] --> b.
144     *
145     * @param data  the data.
146     *
147     * @return The parameters.
148     */
149    public static double[] getPowerRegression(double[][] data) {
150
151        int n = data.length;
152        if (n < 2) {
153            throw new IllegalArgumentException("Not enough data.");
154        }
155
156        double sumX = 0;
157        double sumY = 0;
158        double sumXX = 0;
159        double sumXY = 0;
160        for (int i = 0; i < n; i++) {
161            double x = Math.log(data[i][0]);
162            double y = Math.log(data[i][1]);
163            sumX += x;
164            sumY += y;
165            double xx = x * x;
166            sumXX += xx;
167            double xy = x * y;
168            sumXY += xy;
169        }
170        double sxx = sumXX - (sumX * sumX) / n;
171        double sxy = sumXY - (sumX * sumY) / n;
172        double xbar = sumX / n;
173        double ybar = sumY / n;
174
175        double[] result = new double[2];
176        result[1] = sxy / sxx;
177        result[0] = Math.pow(Math.exp(1.0), ybar - result[1] * xbar);
178
179        return result;
180
181    }
182
183    /**
184     * Returns the parameters 'a' and 'b' for an equation y = ax^b, fitted to
185     * the data using a power regression equation.  The result is returned as
186     * an array, where double[0] --> a, and double[1] --> b.
187     *
188     * @param data  the data.
189     * @param series  the series to fit the regression line against.
190     *
191     * @return The parameters.
192     */
193    public static double[] getPowerRegression(XYDataset data, int series) {
194
195        int n = data.getItemCount(series);
196        if (n < 2) {
197            throw new IllegalArgumentException("Not enough data.");
198        }
199
200        double sumX = 0;
201        double sumY = 0;
202        double sumXX = 0;
203        double sumXY = 0;
204        for (int i = 0; i < n; i++) {
205            double x = Math.log(data.getXValue(series, i));
206            double y = Math.log(data.getYValue(series, i));
207            sumX += x;
208            sumY += y;
209            double xx = x * x;
210            sumXX += xx;
211            double xy = x * y;
212            sumXY += xy;
213        }
214        double sxx = sumXX - (sumX * sumX) / n;
215        double sxy = sumXY - (sumX * sumY) / n;
216        double xbar = sumX / n;
217        double ybar = sumY / n;
218
219        double[] result = new double[2];
220        result[1] = sxy / sxx;
221        result[0] = Math.pow(Math.exp(1.0), ybar - result[1] * xbar);
222
223        return result;
224
225    }
226
227}