private void initialize(double[][][] samples, TwoWayAnovaModel type)
{
// References:
// - http://www.smi.hst.aau.dk/~cdahl/BiostatPhD/ANOVA.pdf
ModelType = type;
Observations = FirstFactorSamples * SecondFactorSamples * Replications;
// Step 1. Initialize all degrees of freedom
int cellDegreesOfFreedom = FirstFactorSamples * SecondFactorSamples - 1;
int aDegreesOfFreedom = FirstFactorSamples - 1;
int bDegreesOfFreedom = SecondFactorSamples - 1;
int abDegreesOfFreedom = cellDegreesOfFreedom - aDegreesOfFreedom - bDegreesOfFreedom;
int errorDegreesOfFreedom = FirstFactorSamples * SecondFactorSamples * (Replications - 1);
int totalDegreesOfFreedom = Observations - 1;
// Step 1. Calculate cell means
cellMeans = new double[FirstFactorSamples, SecondFactorSamples];
double sum = 0;
for (int i = 0; i < samples.Length; i++)
for (int j = 0; j < samples[i].Length; j++)
sum += cellMeans[i, j] = Measures.Mean(samples[i][j]);
// Step 2. Calculate the total mean (grand mean)
totalMean = sum / (FirstFactorSamples * SecondFactorSamples);
// Step 3. Calculate factor means
aMean = new double[FirstFactorSamples];
for (int i = 0; i < samples.Length; i++)
{
sum = 0;
for (int j = 0; j < samples[i].Length; j++)
for (int k = 0; k < samples[i][j].Length; k++)
sum += samples[i][j][k];
aMean[i] = sum / (SecondFactorSamples * Replications);
}
bMean = new double[SecondFactorSamples];
for (int j = 0; j < samples[0].Length; j++)
{
sum = 0;
for (int i = 0; i < samples.Length; i++)
for (int k = 0; k < samples[i][j].Length; k++)
sum += samples[i][j][k];
bMean[j] = sum / (FirstFactorSamples * Replications);
}
// Step 4. Calculate total sum of squares
double ssum = 0;
for (int i = 0; i < samples.Length; i++)
{
for (int j = 0; j < samples[i].Length; j++)
{
for (int k = 0; k < samples[i][j].Length; k++)
{
double u = samples[i][j][k] - totalMean;
ssum += u * u;
}
}
}
double totalSumOfSquares = ssum;
// Step 5. Calculate the cell sum of squares
ssum = 0;
for (int i = 0; i < FirstFactorSamples; i++)
{
for (int j = 0; j < SecondFactorSamples; j++)
{
double u = cellMeans[i, j] - totalMean;
ssum += u * u;
}
}
double cellSumOfSquares = ssum * Replications;
// Step 6. Compute within-cells error sum of squares
ssum = 0;
for (int i = 0; i < samples.Length; i++)
{
for (int j = 0; j < samples[i].Length; j++)
{
for (int k = 0; k < samples[i][j].Length; k++)
{
double u = samples[i][j][k] - cellMeans[i, j];
ssum += u * u;
}
}
}
double errorSumOfSquares = ssum;
// Step 7. Compute factors sum of squares
ssum = 0;
for (int i = 0; i < aMean.Length; i++)
{
double u = aMean[i] - totalMean;
ssum += u * u;
}
double aSumOfSquares = ssum * SecondFactorSamples * Replications;
ssum = 0;
for (int i = 0; i < bMean.Length; i++)
{
double u = bMean[i] - totalMean;
ssum += u * u;
}
double bSumOfSquares = ssum * FirstFactorSamples * Replications;
// Step 9. Compute interaction sum of squares
double abSumOfSquares = cellSumOfSquares - aSumOfSquares - bSumOfSquares;
// Step 10. Compute mean squares
double aMeanSquares = aSumOfSquares / aDegreesOfFreedom;
double bMeanSquares = bSumOfSquares / bDegreesOfFreedom;
double abMeanSquares = abSumOfSquares / abDegreesOfFreedom;
double errorMeanSquares = errorSumOfSquares / errorDegreesOfFreedom;
// Step 10. Create the F-Statistics
FTest aSignificance, bSignificance, abSignificance;
if (type == TwoWayAnovaModel.Fixed)
{
// Model 1: Factors A and B fixed
aSignificance = new FTest(aMeanSquares / abMeanSquares, aDegreesOfFreedom, abDegreesOfFreedom);
bSignificance = new FTest(bMeanSquares / abMeanSquares, bDegreesOfFreedom, abDegreesOfFreedom);
abSignificance = new FTest(abMeanSquares / errorMeanSquares, abDegreesOfFreedom, errorDegreesOfFreedom);
}
else if (type == TwoWayAnovaModel.Mixed)
{
// Model 2: Factors A and B random
aSignificance = new FTest(aMeanSquares / errorMeanSquares, aDegreesOfFreedom, errorDegreesOfFreedom);
bSignificance = new FTest(bMeanSquares / errorMeanSquares, bDegreesOfFreedom, errorDegreesOfFreedom);
abSignificance = new FTest(abMeanSquares / errorMeanSquares, abDegreesOfFreedom, errorDegreesOfFreedom);
}
else if (type == TwoWayAnovaModel.Random)
{
// Model 3: Factor A fixed, factor B random
aSignificance = new FTest(aMeanSquares / abMeanSquares, aDegreesOfFreedom, abDegreesOfFreedom);
bSignificance = new FTest(bMeanSquares / errorMeanSquares, bDegreesOfFreedom, errorDegreesOfFreedom);
abSignificance = new FTest(abMeanSquares / errorMeanSquares, abDegreesOfFreedom, errorDegreesOfFreedom);
}
else throw new ArgumentException("Unhandled analysis type.","type");
// Step 11. Create the ANOVA table and sources
AnovaVariationSource cell = new AnovaVariationSource(this, "Cells", cellSumOfSquares, cellDegreesOfFreedom);
AnovaVariationSource a = new AnovaVariationSource(this, "Factor A", aSumOfSquares, aDegreesOfFreedom, aMeanSquares, aSignificance);
AnovaVariationSource b = new AnovaVariationSource(this, "Factor B", bSumOfSquares, bDegreesOfFreedom, bMeanSquares, bSignificance);
AnovaVariationSource ab = new AnovaVariationSource(this, "Interaction AxB", abSumOfSquares, abDegreesOfFreedom, abMeanSquares, abSignificance);
AnovaVariationSource error = new AnovaVariationSource(this, "Within-cells (error)", errorSumOfSquares, errorDegreesOfFreedom, errorMeanSquares);
AnovaVariationSource total = new AnovaVariationSource(this, "Total", totalSumOfSquares, totalDegreesOfFreedom);
this.Sources = new TwoWayAnovaVariationSources()
{
Cells = cell,
FactorA = a,
FactorB = b,
Interaction = ab,
Error = error,
Total = total
};
this.Table = new AnovaSourceCollection(cell, a, b, ab, error, total);
}
}