001 /* ===========================================================
002 * JFreeChart : a free chart library for the Java(tm) platform
003 * ===========================================================
004 *
005 * (C) Copyright 2000-2007, 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-2007, 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
044 package org.jfree.data.statistics;
045
046 import org.jfree.data.xy.XYDataset;
047
048 /**
049 * A utility class for fitting regression curves to data.
050 */
051 public 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 }