* Modified multiple regression newSample methods to ensure that by default in all cases,

regression models are estimated with intercept terms.  Prior to the fix for this issue, 
  newXSampleData(double[][]), newSampleData(double[], double[][]) and 
  newSampleData(double[], double[][], double[][]) all required columns of "1's"
  to be inserted into the x[][] arrays to create a model with an intercept term;
  while newSampleData(double[], int, int) created a model including an intercept
  term without requiring the unitary column.  All methods have  been changed to
  eliminate the need for users to add unitary columns to specify regression models.
* Improved javadoc
* Improved tests
JIRA: MATH-411

git-svn-id: https://svn.apache.org/repos/asf/commons/proper/math/branches/MATH_2_X@993574 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Phil Steitz 2010-09-08 01:24:51 +00:00
parent a7cfaf46e3
commit 995efe1ead
8 changed files with 313 additions and 61 deletions

View File

@ -126,6 +126,7 @@ public enum LocalizedFormats implements Localizable {
INVALID_INTERVAL_INITIAL_VALUE_PARAMETERS("invalid interval, initial value parameters: lower={0}, initial={1}, upper={2}"),
INVALID_ITERATIONS_LIMITS("invalid iteration limits: min={0}, max={1}"),
INVALID_MAX_ITERATIONS("bad value for maximum iterations number: {0}"),
INVALID_REGRESSION_ARRAY("input data array length = {0} does not match the number of observations = {1} and the number of regressors = {2}"),
INVALID_ROUNDING_METHOD("invalid rounding method {0}, valid methods: {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}), {11} ({12}), {13} ({14}), {15} ({16})"),
ITERATOR_EXHAUSTED("iterator exhausted"),
LCM_OVERFLOW_32_BITS("overflow: lcm({0}, {1}) is 2^31"),

View File

@ -40,14 +40,47 @@ public abstract class AbstractMultipleLinearRegression implements
protected RealVector Y;
/**
* Loads model x and y sample data from a flat array of data, overriding any previous sample.
* Assumes that rows are concatenated with y values first in each row.
* <p>Loads model x and y sample data from a flat input array, overriding any previous sample.
* </p>
* <p>Assumes that rows are concatenated with y values first in each row. For example, an input
* <code>data</code> array containing the sequence of values (1, 2, 3, 4, 5, 6, 7, 8, 9) with
* <code>nobs = 3</code> and <code>nvars = 2</code> creates a regression dataset with two
* independent variables, as below:
* <pre>
* y x[0] x[1]
* --------------
* 1 2 3
* 4 5 6
* 7 8 9
* </pre>
* </p>
* <p>Note that there is no need to add an initial unitary column (column of 1's) when
* specifying a model including an intercept term.
* </p>
* <p>Throws IllegalArgumentException if any of the following preconditions fail:
* <ul><li><code>data</code> cannot be null</li>
* <li><code>data.length = nobs * (nvars + 1)</li>
* <li><code>nobs > nvars</code></li></ul>
* </p>
*
* @param data input data array
* @param nobs number of observations (rows)
* @param nvars number of independent variables (columns, not counting y)
* @throws IllegalArgumentException if the preconditions are not met
*/
public void newSampleData(double[] data, int nobs, int nvars) {
if (data == null) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NULL_NOT_ALLOWED);
}
if (data.length != nobs * (nvars + 1)) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.INVALID_REGRESSION_ARRAY, data.length, nobs, nvars);
}
if (nobs <= nvars) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NOT_ENOUGH_DATA_FOR_NUMBER_OF_PREDICTORS);
}
double[] y = new double[nobs];
double[][] x = new double[nobs][nvars + 1];
int pointer = 0;
@ -63,30 +96,82 @@ public abstract class AbstractMultipleLinearRegression implements
}
/**
* Loads new y sample data, overriding any previous sample
* Loads new y sample data, overriding any previous data.
*
* @param y the [n,1] array representing the y sample
* @param y the array representing the y sample
* @throws IllegalArgumentException if y is null or empty
*/
protected void newYSampleData(double[] y) {
if (y == null) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NULL_NOT_ALLOWED);
}
if (y.length == 0) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NO_DATA);
}
this.Y = new ArrayRealVector(y);
}
/**
* Loads new x sample data, overriding any previous sample
*
* @param x the [n,k] array representing the x sample
* <p>Loads new x sample data, overriding any previous data.
* </p>
* The input <code>x</code> array should have one row for each sample
* observation, with columns corresponding to independent variables.
* For example, if <pre>
* <code> x = new double[][] {{1, 2}, {3, 4}, {5, 6}} </code></pre>
* then <code>setXSampleData(x) </code> results in a model with two independent
* variables and 3 observations:
* <pre>
* x[0] x[1]
* ----------
* 1 2
* 3 4
* 5 6
* </pre>
* </p>
* <p>Note that there is no need to add an initial unitary column (column of 1's) when
* specifying a model including an intercept term.
* </p>
* @param x the rectangular array representing the x sample
* @throws IllegalArgumentException if x is null, empty or not rectangular
*/
protected void newXSampleData(double[][] x) {
this.X = new Array2DRowRealMatrix(x);
if (x == null) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NULL_NOT_ALLOWED);
}
if (x.length == 0) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NO_DATA);
}
final int nVars = x[0].length;
final double[][] xAug = new double[x.length][nVars + 1];
for (int i = 0; i < x.length; i++) {
if (x[i].length != nVars) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.DIFFERENT_ROWS_LENGTHS,
x[i].length, nVars);
}
xAug[i][0] = 1.0d;
System.arraycopy(x[i], 0, xAug[i], 1, nVars);
}
this.X = new Array2DRowRealMatrix(xAug, false);
}
/**
* Validates sample data.
* Validates sample data. Checks that
* <ul><li>Neither x nor y is null or empty;</li>
* <li>The length (i.e. number of rows) of x equals the length of y</li>
* <li>x has at least one more row than it has columns (i.e. there is
* sufficient data to estimate regression coefficients for each of the
* columns in x plus an intercept.</li>
* </ul>
*
* @param x the [n,k] array representing the x data
* @param y the [n,1] array representing the y data
* @throws IllegalArgumentException if any of the checks fail
*
* @param x the [n,k] array representing the x sample
* @param y the [n,1] array representing the y sample
* @throws IllegalArgumentException if the x and y array data are not
* compatible for the regression
*/
protected void validateSampleData(double[][] x, double[] y) {
if ((x == null) || (y == null) || (x.length != y.length)) {
@ -94,7 +179,12 @@ public abstract class AbstractMultipleLinearRegression implements
LocalizedFormats.DIMENSIONS_MISMATCH_SIMPLE,
(x == null) ? 0 : x.length,
(y == null) ? 0 : y.length);
} else if ((x.length > 0) && (x[0].length > x.length)) {
}
if (x.length == 0) { // Must be no y data either
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NO_DATA);
}
if (x[0].length + 1 > x.length) {
throw MathRuntimeException.createIllegalArgumentException(
LocalizedFormats.NOT_ENOUGH_DATA_FOR_NUMBER_OF_PREDICTORS,
x.length, x[0].length);
@ -102,12 +192,13 @@ public abstract class AbstractMultipleLinearRegression implements
}
/**
* Validates sample data.
* Validates that the x data and covariance matrix have the same
* number of rows and that the covariance matrix is square.
*
* @param x the [n,k] array representing the x sample
* @param covariance the [n,n] array representing the covariance matrix
* @throws IllegalArgumentException if the x sample data or covariance
* matrix are not compatible for the regression
* @throws IllegalArgumentException if the number of rows in x is not equal
* to the number of rows in covariance or covariance is not square.
*/
protected void validateCovarianceData(double[][] x, double[][] covariance) {
if (x.length != covariance.length) {

View File

@ -77,8 +77,7 @@ public class OLSMultipleLinearRegression extends AbstractMultipleLinearRegressio
/**
* {@inheritDoc}
*
* Computes and caches QR decomposition of the X matrix
* <p>This implementation computes and caches the QR decomposition of the X matrix.</p>
*/
@Override
public void newSampleData(double[] data, int nobs, int nvars) {
@ -132,7 +131,7 @@ public class OLSMultipleLinearRegression extends AbstractMultipleLinearRegressio
}
/**
* Returns the sum of square residuals.
* Returns the sum of squared residuals.
*
* @return residual sum of squares
*/
@ -168,22 +167,20 @@ public class OLSMultipleLinearRegression extends AbstractMultipleLinearRegressio
final double n = X.getRowDimension();
return 1 - (calculateResidualSumOfSquares() * (n - 1)) /
(calculateTotalSumOfSquares() * (n - X.getColumnDimension()));
// return 1 - ((1 - calculateRSquare()) * (n - 1) / (n - X.getColumnDimension() - 1));
}
/**
* Loads new x sample data, overriding any previous sample
*
* @param x the [n,k] array representing the x sample
* {@inheritDoc}
* <p>This implementation computes and caches the QR decomposition of the X matrix once it is successfully loaded.</p>
*/
@Override
protected void newXSampleData(double[][] x) {
this.X = new Array2DRowRealMatrix(x);
super.newXSampleData(x);
qr = new QRDecompositionImpl(X);
}
/**
* Calculates regression coefficients using OLS.
* Calculates the regression coefficients using OLS.
*
* @return beta
*/

View File

@ -98,6 +98,7 @@ INVALID_BRACKETING_PARAMETERS = param\u00e8tres d''encadrement invalides : borne
INVALID_INTERVAL_INITIAL_VALUE_PARAMETERS = param\u00e8tres de l''intervalle initial invalides : borne inf = {0}, valeur initiale = {1}, borne sup = {2}
INVALID_ITERATIONS_LIMITS = limites d''it\u00e9rations invalides : min = {0}, max = {1}
INVALID_MAX_ITERATIONS = valeur invalide pour le nombre maximal d''it\u00e9rations : {0}
INVALID_REGRESSION_ARRAY= longueur du tableau de donn\u00e9es = {0} ne correspond pas au nombre d'observations = {1} et le nombre de variables explicatives = {2}
INVALID_ROUNDING_METHOD = m\u00e9thode d''arondi {0} invalide, m\u00e9thodes valides : {1} ({2}), {3} ({4}), {5} ({6}), {7} ({8}), {9} ({10}), {11} ({12}), {13} ({14}), {15} ({16})
ITERATOR_EXHAUSTED = it\u00e9ration achev\u00e9e
LCM_OVERFLOW_32_BITS = d\u00e9passement de capacit\u00e9 : le MCM de {0} et {1} vaut 2^31

View File

@ -52,6 +52,19 @@ The <action> type attribute can be add,update,fix,remove.
If the output is not quite correct, check for invisible trailing spaces!
-->
<release version="2.2" date="TBD" description="TBD">
<action dev="psteitz" type="fix" issue="MATH-411">
Modified multiple regression newSample methods to ensure that by default in all cases,
regression models are estimated with intercept terms. Prior to the fix for this issue,
newXSampleData(double[][]), newSampleData(double[], double[][]) and
newSampleData(double[], double[][], double[][]) all required columns of "1's" to be inserted
into the x[][] arrays to create a model with an intercept term; while newSampleData(double[], int, int)
created a model including an intercept term without requiring the unitary column. All methods have
been changed to eliminate the need for users to add unitary columns to specify regression models.
<!-- uncomment when MATH-409 is resolved (noIntercept option)
Users of OLSMultipleLinearRegression or GLSMultipleLinearRegression versions 2.0 or 2.1 should either
verify that their code either does not use the first set of data loading methods above or set the noIntercept
property on estimated models to get the previous behavior. -->
</action>
<action dev="luc" type="fix" issue="MATH-412" due-to="Bill Rossi">
Added the dfp library providing arbitrary precision floating point computation in the spirit of
IEEE 854-1987 (not exactly as it uses base 1000 instead of base 10). In addition to finite numbers,

View File

@ -16,10 +16,13 @@
*/
package org.apache.commons.math.stat.regression;
import static org.junit.Assert.assertEquals;
import org.junit.Before;
import org.junit.Test;
import org.apache.commons.math.TestUtils;
import org.apache.commons.math.stat.StatUtils;
import org.apache.commons.math.linear.MatrixUtils;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.RealVector;
public class GLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbstractTest {
@ -32,12 +35,12 @@ public class GLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
public void setUp(){
y = new double[]{11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
x = new double[6][];
x[0] = new double[]{1.0, 0, 0, 0, 0, 0};
x[1] = new double[]{1.0, 2.0, 0, 0, 0, 0};
x[2] = new double[]{1.0, 0, 3.0, 0, 0, 0};
x[3] = new double[]{1.0, 0, 0, 4.0, 0, 0};
x[4] = new double[]{1.0, 0, 0, 0, 5.0, 0};
x[5] = new double[]{1.0, 0, 0, 0, 0, 6.0};
x[0] = new double[]{0, 0, 0, 0, 0};
x[1] = new double[]{2.0, 0, 0, 0, 0};
x[2] = new double[]{0, 3.0, 0, 0, 0};
x[3] = new double[]{0, 0, 4.0, 0, 0};
x[4] = new double[]{0, 0, 0, 5.0, 0};
x[5] = new double[]{0, 0, 0, 0, 6.0};
omega = new double[6][];
omega[0] = new double[]{1.0, 0, 0, 0, 0, 0};
omega[1] = new double[]{0, 2.0, 0, 0, 0, 0};
@ -115,7 +118,7 @@ public class GLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
@Override
protected int getNumberOfRegressors() {
return x[0].length;
return x[0].length + 1;
}
@Override
@ -135,4 +138,69 @@ public class GLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
model.newSampleData(y, x, omega);
TestUtils.assertEquals(model.calculateYVariance(), 3.5, 0);
}
/**
* Verifies that setting X, Y and covariance separately has the same effect as newSample(X,Y,cov).
*/
@Test
public void testNewSample2() throws Exception {
double[] y = new double[] {1, 2, 3, 4};
double[][] x = new double[][] {
{19, 22, 33},
{20, 30, 40},
{25, 35, 45},
{27, 37, 47}
};
double[][] covariance = MatrixUtils.createRealIdentityMatrix(4).scalarMultiply(2).getData();
GLSMultipleLinearRegression regression = new GLSMultipleLinearRegression();
regression.newSampleData(y, x, covariance);
RealMatrix combinedX = regression.X.copy();
RealVector combinedY = regression.Y.copy();
RealMatrix combinedCovInv = regression.getOmegaInverse();
regression.newXSampleData(x);
regression.newYSampleData(y);
assertEquals(combinedX, regression.X);
assertEquals(combinedY, regression.Y);
assertEquals(combinedCovInv, regression.getOmegaInverse());
}
/**
* Verifies that GLS with identity covariance matrix gives the same results
* as OLS.
*/
@Test
public void testGLSOLSConsistency() throws Exception {
// Use Longley data to test
double[] design = new double[] {
60323,83.0,234289,2356,1590,107608,1947,
61122,88.5,259426,2325,1456,108632,1948,
60171,88.2,258054,3682,1616,109773,1949,
61187,89.5,284599,3351,1650,110929,1950,
63221,96.2,328975,2099,3099,112075,1951,
63639,98.1,346999,1932,3594,113270,1952,
64989,99.0,365385,1870,3547,115094,1953,
63761,100.0,363112,3578,3350,116219,1954,
66019,101.2,397469,2904,3048,117388,1955,
67857,104.6,419180,2822,2857,118734,1956,
68169,108.4,442769,2936,2798,120445,1957,
66513,110.8,444546,4681,2637,121950,1958,
68655,112.6,482704,3813,2552,123366,1959,
69564,114.2,502601,3931,2514,125368,1960,
69331,115.7,518173,4806,2572,127852,1961,
70551,116.9,554894,4007,2827,130081,1962
};
RealMatrix identityCov = MatrixUtils.createRealIdentityMatrix(16);
GLSMultipleLinearRegression glsModel = new GLSMultipleLinearRegression();
OLSMultipleLinearRegression olsModel = new OLSMultipleLinearRegression();
glsModel.newSampleData(design, 16, 6);
olsModel.newSampleData(design, 16, 6);
glsModel.newCovarianceData(identityCov.getData());
double[] olsBeta = olsModel.calculateBeta().getData();
double[] glsBeta = glsModel.calculateBeta().getData();
// TODO: Should have assertRelativelyEquals(double[], double[], eps) in TestUtils
// Should also add RealVector and RealMatrix versions
for (int i = 0; i < olsBeta.length; i++) {
TestUtils.assertRelativelyEquals(olsBeta[i], glsBeta[i], 10E-7);
}
}
}

View File

@ -16,6 +16,8 @@
*/
package org.apache.commons.math.stat.regression;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.RealVector;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@ -25,14 +27,14 @@ import org.junit.Test;
public abstract class MultipleLinearRegressionAbstractTest {
protected MultipleLinearRegression regression;
protected AbstractMultipleLinearRegression regression;
@Before
public void setUp(){
regression = createRegression();
}
protected abstract MultipleLinearRegression createRegression();
protected abstract AbstractMultipleLinearRegression createRegression();
protected abstract int getNumberOfRegressors();
@ -63,5 +65,62 @@ public abstract class MultipleLinearRegressionAbstractTest {
assertTrue(variance > 0.0);
}
}
/**
* Verifies that newSampleData methods consistently insert unitary columns
* in design matrix. Confirms the fix for MATH-411.
*/
@Test
public void testNewSample() throws Exception {
double[] design = new double[] {
1, 19, 22, 33,
2, 20, 30, 40,
3, 25, 35, 45,
4, 27, 37, 47
};
double[] y = new double[] {1, 2, 3, 4};
double[][] x = new double[][] {
{19, 22, 33},
{20, 30, 40},
{25, 35, 45},
{27, 37, 47}
};
AbstractMultipleLinearRegression regression = (AbstractMultipleLinearRegression) createRegression();
regression.newSampleData(design, 4, 3);
RealMatrix flatX = regression.X.copy();
RealVector flatY = regression.Y.copy();
regression.newXSampleData(x);
regression.newYSampleData(y);
assertEquals(flatX, regression.X);
assertEquals(flatY, regression.Y);
}
@Test(expected=IllegalArgumentException.class)
public void testNewSampleNullData() throws Exception {
double[] data = null;
createRegression().newSampleData(data, 2, 3);
}
@Test(expected=IllegalArgumentException.class)
public void testNewSampleInvalidData() throws Exception {
double[] data = new double[] {1, 2, 3, 4};
createRegression().newSampleData(data, 2, 3);
}
@Test(expected=IllegalArgumentException.class)
public void testNewSampleInsufficientData() throws Exception {
double[] data = new double[] {1, 2, 3, 4};
createRegression().newSampleData(data, 1, 3);
}
@Test(expected=IllegalArgumentException.class)
public void testXSampleDataNull() {
createRegression().newXSampleData(null);
}
@Test(expected=IllegalArgumentException.class)
public void testYSampleDataNull() {
createRegression().newYSampleData(null);
}
}

View File

@ -24,6 +24,7 @@ import org.apache.commons.math.linear.MatrixUtils;
import org.apache.commons.math.linear.MatrixVisitorException;
import org.apache.commons.math.linear.RealMatrix;
import org.apache.commons.math.linear.Array2DRowRealMatrix;
import org.apache.commons.math.linear.RealVector;
import org.apache.commons.math.stat.StatUtils;
import org.junit.Before;
import org.junit.Test;
@ -38,12 +39,12 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
public void setUp(){
y = new double[]{11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
x = new double[6][];
x[0] = new double[]{1.0, 0, 0, 0, 0, 0};
x[1] = new double[]{1.0, 2.0, 0, 0, 0, 0};
x[2] = new double[]{1.0, 0, 3.0, 0, 0, 0};
x[3] = new double[]{1.0, 0, 0, 4.0, 0, 0};
x[4] = new double[]{1.0, 0, 0, 0, 5.0, 0};
x[5] = new double[]{1.0, 0, 0, 0, 0, 6.0};
x[0] = new double[]{0, 0, 0, 0, 0};
x[1] = new double[]{2.0, 0, 0, 0, 0};
x[2] = new double[]{0, 3.0, 0, 0, 0};
x[3] = new double[]{0, 0, 4.0, 0, 0};
x[4] = new double[]{0, 0, 0, 5.0, 0};
x[5] = new double[]{0, 0, 0, 0, 6.0};
super.setUp();
}
@ -56,24 +57,14 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
@Override
protected int getNumberOfRegressors() {
return x[0].length;
return x[0].length + 1;
}
@Override
protected int getSampleSize() {
return y.length;
}
@Test(expected=IllegalArgumentException.class)
public void cannotAddXSampleData() {
createRegression().newSampleData(new double[]{}, null);
}
@Test(expected=IllegalArgumentException.class)
public void cannotAddNullYSampleData() {
createRegression().newSampleData(null, new double[][]{});
}
@Test(expected=IllegalArgumentException.class)
public void cannotAddSampleDataWithSizeMismatch() {
double[] y = new double[]{1.0, 2.0};
@ -248,17 +239,16 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
44.7,46.6,16,29,50.43,
42.8,27.7,22,29,58.33
};
// Transform to Y and X required by interface
int nobs = 47;
int nvars = 4;
final int nobs = 47;
final int nvars = 4;
// Estimate the model
OLSMultipleLinearRegression model = new OLSMultipleLinearRegression();
model.newSampleData(design, nobs, nvars);
// Check expected beta values from R
double[] betaHat = model.estimateRegressionParameters();
final double[] betaHat = model.estimateRegressionParameters();
TestUtils.assertEquals(betaHat,
new double[]{91.05542390271397,
-0.22064551045715,
@ -267,7 +257,7 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
0.12441843147162}, 1E-12);
// Check expected residuals from R
double[] residuals = model.estimateResiduals();
final double[] residuals = model.estimateResiduals();
TestUtils.assertEquals(residuals, new double[]{
7.1044267859730512,1.6580347433531366,
4.6944952770029644,8.4548022690166160,13.6547432343186212,
@ -288,7 +278,7 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
1E-12);
// Check standard errors from R
double[] errors = model.estimateRegressionParametersStandardErrors();
final double[] errors = model.estimateRegressionParametersStandardErrors();
TestUtils.assertEquals(new double[] {6.94881329475087,
0.07360008972340,
0.27410957467466,
@ -404,4 +394,36 @@ public class OLSMultipleLinearRegressionTest extends MultipleLinearRegressionAbs
model.calculateErrorVariance() * (X.getRowDimension() - X.getColumnDimension()), 1E-20);
}
/**
* Verifies that setting X and Y separately has the same effect as newSample(X,Y).
*/
@Test
public void testNewSample2() throws Exception {
double[] y = new double[] {1, 2, 3, 4};
double[][] x = new double[][] {
{19, 22, 33},
{20, 30, 40},
{25, 35, 45},
{27, 37, 47}
};
OLSMultipleLinearRegression regression = new OLSMultipleLinearRegression();
regression.newSampleData(y, x);
RealMatrix combinedX = regression.X.copy();
RealVector combinedY = regression.Y.copy();
regression.newXSampleData(x);
regression.newYSampleData(y);
assertEquals(combinedX, regression.X);
assertEquals(combinedY, regression.Y);
}
@Test(expected=IllegalArgumentException.class)
public void testNewSampleDataYNull() {
createRegression().newSampleData(null, new double[][] {});
}
@Test(expected=IllegalArgumentException.class)
public void testNewSampleDataXNull() {
createRegression().newSampleData(new double[] {}, null);
}
}