← All NMath Code Examples
using System;
namespace CenterSpace.NMath.Examples.CSharp
{
/// <summary>
/// A .NET example in C# showing some of the advanced features of the class
/// TwoWayAnova.
/// </summary>
class AdvancedTwoWayAnovaExample
{
private static string materialColumnName_ = "Material";
private static string tempColumnName_ = "Temperature";
private static string lifetimeColumnName_ = "Lifetime";
static void Main( string[] args )
{
// Create the DataFrame that will hold the data to analyze. The variable
// being measured is battery lifetime. The two factors are material and
// temperature. The data must have at least three columns. One column
// must be numeric and contain the values of the variable being measured,
// battery life in this case, the other two columns must contain the values
// of the two factors that correspond to the measurement. Thus a row of the
// the DataFrame that we are going to use contains a value for the battery
// material (M1, M2, or M3), a temperature (15, 70, or 175), and a lifetime
// (in hours). The method CreateBatteryData() builds the DataFrame.
DataFrame batteryData = CreateBatteryData();
// Now create a TwoWayAnova object from the battery data. The three
// integer arguments indicate the following column indices, respectively:
// index of the column containing factor A, index of the column containing
/// factor B, index of the column containing the measured values.
var anova = new TwoWayAnova( batteryData, 0, 1, 2 );
// Class TwoWayAnova provides access to the data in a particular
// cell. A cell is defined by the values of the two factors. For
// example, the following code prints out all the battery lifetimes
// for batteries made from material M2 at temperature 70.
DFNumericColumn mTwoSeventyValues = anova.GetCellData( materialColumnName_, "M2",
tempColumnName_, "70" );
Console.WriteLine();
Console.WriteLine( "Lifetimes of M2 batteries at 70 degrees: {0}", mTwoSeventyValues );
// You can also get the means for each cell:
double mean = anova.GetMeanForCell( materialColumnName_, "M2", tempColumnName_, "70" );
Console.WriteLine( "Mean lifetime of M2 batteries at 70 degrees: {0}", mean );
// Means for a given factor level can also be accessed. For example, the
// following code gets the mean lifetime for all batteries made from material
// M1
mean = anova.GetMeanForFactorLevel( materialColumnName_, "M1" );
Console.WriteLine( "Mean lifetime for M1 batteries = {0}", mean );
// You can also get the grand mean.
Console.WriteLine( "Overall mean lifetime is {0}", anova.GrandMean );
// The TwoWayAnovaTable class is used to access all the traditional
// two way ANOVA data.
TwoWayAnovaTable anovaTable = anova.AnovaTable;
Console.WriteLine( Environment.NewLine + "Source: " + materialColumnName_ );
Console.WriteLine( " Degrees of Freedom: {0}", anovaTable.DegreesOfFreedom( materialColumnName_ ) );
Console.WriteLine( " Sum of Squares : {0}", anovaTable.SumOfSquares( materialColumnName_ ) );
Console.WriteLine( " Mean Square : {0}", anovaTable.MeanSquare( materialColumnName_ ) );
Console.WriteLine( " F : {0}", anovaTable.Fstatistic( materialColumnName_ ) );
Console.WriteLine( " P : {0}", anovaTable.FstatisticPvalue( materialColumnName_ ) );
Console.WriteLine( Environment.NewLine + "Source: " + tempColumnName_ );
Console.WriteLine( " Degrees of Freedom: {0}", anovaTable.DegreesOfFreedom( tempColumnName_ ) );
Console.WriteLine( " Sum of Squares : {0}", anovaTable.SumOfSquares( tempColumnName_ ) );
Console.WriteLine( " Mean Square : {0}", anovaTable.MeanSquare( tempColumnName_ ) );
Console.WriteLine( " F : {0}", anovaTable.Fstatistic( tempColumnName_ ) );
Console.WriteLine( " P : {0}", anovaTable.FstatisticPvalue( tempColumnName_ ) );
Console.WriteLine( Environment.NewLine + "Source: Interaction" );
Console.WriteLine( " Degrees of Freedom: {0}", anovaTable.InteractionDegreesOfFreedom );
Console.WriteLine( " Sum of Squares : {0}", anovaTable.InteractionSumOfSquares );
Console.WriteLine( " Mean Square : {0}", anovaTable.InteractionMeanSquare );
Console.WriteLine( " F : {0}", anovaTable.InteractionFstatistic );
Console.WriteLine( " P : {0}", anovaTable.InteractionFstatisticPvalue );
Console.WriteLine( Environment.NewLine + "Source: Error" );
Console.WriteLine( " Degrees of Freedom: {0}", anovaTable.ErrorDegreesOfFreedom );
Console.WriteLine( " Sum of Squares : {0}", anovaTable.ErrorSumOfSquares );
Console.WriteLine( " Mean Square : {0}", anovaTable.ErrorMeanSquare );
Console.WriteLine( Environment.NewLine + "Total" );
Console.WriteLine( " Degrees of Freedom: {0}", anovaTable.TotalDegreesOfFreedom );
Console.WriteLine( " Sum of Squares : {0}", anovaTable.TotalSumOfSquares );
// Class TwoWayAnova computes a two way ANOVA using a multiple linear
// regression. The following function prints out details of the regression.
// See the function WriteRegressionInfo() for more information.
Console.WriteLine( Environment.NewLine + "-------- Regression Information -----------" );
WriteRegressionInfo( anova );
Console.WriteLine();
Console.WriteLine( "Press Enter Key" );
Console.Read();
}
/// <summary>
/// Two way ANOVAs are computed using a multiple linear regression. The
/// details of this regression are available from the TwoWayAnova class.
/// This functions shows how to access these details and sends the
/// information to the Console.
/// </summary>
/// <param name="anova">ANOVA to process.</param>
private static void WriteRegressionInfo( TwoWayAnova anova )
{
// A multiple linear regression is used to solve a two way ANOVA
// problem by creating dummy variables using an encoding. The
// TwoWayAnova class uses "effects" encoding to accomplish this.
// In effects encoding we define k - 1 dummy variables to encode
// k levels of the factor in interest. A dummy variable di for the
// the ith level is then defined as
//
// di = 1 if ith level,
// di = -1 if kth level,
// di = 0 otherwise
//
// If factor A has k levels, and factor B has m levels, there will also
// be (k - 1) * (m - 1) interaction variables in the regression. It
// follows that there will not be a regression parameter for every factor
// level, or interaction. In the code below you will notice that we check
// for a null return value when attempting to retrieve a regression
// parameter object for a particular factor level or interaction of
// factor levels. This is the reason.
// First print out information for the intercept parameter. The class
// AnovaRegressionParameter is derived from LinearRegressionParameter.
// It merely adds the SumOfSquares property.
AnovaRegressionParameter interceptParam = anova.RegressionInterceptParameter;
Console.WriteLine( Environment.NewLine + "Parameter: Intercept" );
Console.WriteLine( " Estimate : {0}", interceptParam.Value );
Console.WriteLine( " Standard Error : {0}", interceptParam.StandardError );
Console.WriteLine( " T for H0 Parameter = 0: {0}", interceptParam.TStatistic( 0 ) );
Console.WriteLine( " Prob > |T| : {0}", interceptParam.TStatisticPValue( 0 ) );
Console.WriteLine( " Type I SS : {0}", interceptParam.SumOfSquares );
Console.WriteLine( " Variable Label: INTERCEPT" + Environment.NewLine );
// Next print out information for the Material factor parameters. Since there
// is one less parameters than there are levels, well have to check for null
// return values from GetRegressionFactorParameter().
// AnovaRegressionFactorParam is derived from AnovaRegressionParameter, and
// hence from LinearRegressionParameter, adding the Encoding property.
AnovaRegressionFactorParam factorParam;
string[] materialLevels = { "M1", "M2", "M3" };
for ( int i = 0; i < materialLevels.Length; ++i )
{
factorParam = anova.GetRegressionFactorParameter( materialColumnName_, materialLevels[i] );
if ( factorParam == null )
{
continue;
}
Console.WriteLine( string.Format( "Parameter: {0}", materialLevels[i] ) );
Console.WriteLine( " Estimate : {0}", factorParam.Value );
Console.WriteLine( " Standard Error : {0}", factorParam.StandardError );
Console.WriteLine( " T for H0 Parameter = 0: {0}", factorParam.TStatistic( 0 ) );
Console.WriteLine( " Prob > |T| : {0}", factorParam.TStatisticPValue( 0 ) );
Console.WriteLine( " Type I SS : {0}", factorParam.SumOfSquares );
string encoding = string.Format( " Variable Label: dummy variable = {0} if {1} = {2}",
factorParam.Encoding, materialColumnName_, materialLevels[i] );
Console.WriteLine( encoding + Environment.NewLine );
}
// Now, do the same for the temperature factor parameter.
string[] tempLevels = { "15", "70", "125" };
for ( int i = 0; i < materialLevels.Length; ++i )
{
factorParam = anova.GetRegressionFactorParameter( tempColumnName_, tempLevels[i] );
if ( factorParam == null )
{
continue;
}
Console.WriteLine( string.Format( "Parameter: {0}", tempLevels[i] ) );
Console.WriteLine( " Estimate : {0}", factorParam.Value );
Console.WriteLine( " Standard Error : {0}", factorParam.StandardError );
Console.WriteLine( " T for H0 Parameter = 0: {0}", factorParam.TStatistic( 0 ) );
Console.WriteLine( " Prob > |T| : {0}", factorParam.TStatisticPValue( 0 ) );
Console.WriteLine( " Type I SS : {0}", factorParam.SumOfSquares );
string encoding = string.Format( " Variable Label: dummy variable = {0} if {1} = {2}",
factorParam.Encoding, tempColumnName_, tempLevels[i] );
Console.WriteLine( encoding + Environment.NewLine );
}
// Finally, print out information for the interaction parameters.
// AnovaRegressionInteractionParam is derived from AnovaRegressionParameter, and
// hence from LinearRegressionParameter. It does not contain an Encoding
// property. The value of the interaction variables is just the product of
// the values of their corresponding factor variables.
AnovaRegressionInteractionParam interactionParam;
for ( int i = 0; i < materialLevels.Length; ++i )
{
for ( int j = 0; j < tempLevels.Length; ++j )
{
interactionParam = anova.GetRegressionInteractionParameter( materialColumnName_, materialLevels[i],
tempColumnName_, tempLevels[j] );
if ( interactionParam == null )
{
continue;
}
Console.WriteLine( string.Format( "Parameter: {0}, {1}", materialLevels[i], tempLevels[j] ) );
Console.WriteLine( " Estimate : {0}", interactionParam.Value );
Console.WriteLine( " Standard Error : {0}", interactionParam.StandardError );
Console.WriteLine( " T for H0 Parameter = 0: {0}", interactionParam.TStatistic( 0 ) );
Console.WriteLine( " Prob > |T| : {0}", interactionParam.TStatisticPValue( 0 ) );
Console.WriteLine( " Type I SS : {0}", interactionParam.SumOfSquares );
string encoding = string.Format( " Variable Label: interaction of {0} and {1}",
materialLevels[i], tempLevels[j] );
Console.WriteLine( encoding + Environment.NewLine );
}
}
}
private static DataFrame CreateBatteryData()
{
var data = new DataFrame();
data.AddColumn( new DFStringColumn( materialColumnName_ ) );
data.AddColumn( new DFStringColumn( tempColumnName_ ) );
var batteryLifetimeColumn = new DFIntColumn( lifetimeColumnName_ );
data.AddColumn( batteryLifetimeColumn );
int rowNumber = 0;
data.AddRow( ++rowNumber, "M1", "15", 130 );
data.AddRow( ++rowNumber, "M1", "15", 155 );
data.AddRow( ++rowNumber, "M1", "15", 74 );
data.AddRow( ++rowNumber, "M1", "15", 180 );
data.AddRow( ++rowNumber, "M1", "70", 34 );
data.AddRow( ++rowNumber, "M1", "70", 40 );
data.AddRow( ++rowNumber, "M1", "70", 80 );
data.AddRow( ++rowNumber, "M1", "70", 75 );
data.AddRow( ++rowNumber, "M1", "125", 20 );
data.AddRow( ++rowNumber, "M1", "125", 70 );
data.AddRow( ++rowNumber, "M1", "125", 82 );
data.AddRow( ++rowNumber, "M1", "125", 58 );
data.AddRow( ++rowNumber, "M2", "15", 150 );
data.AddRow( ++rowNumber, "M2", "15", 188 );
data.AddRow( ++rowNumber, "M2", "15", 159 );
data.AddRow( ++rowNumber, "M2", "15", 126 );
data.AddRow( ++rowNumber, "M2", "70", 136 );
data.AddRow( ++rowNumber, "M2", "70", 122 );
data.AddRow( ++rowNumber, "M2", "70", 106 );
data.AddRow( ++rowNumber, "M2", "70", 115 );
data.AddRow( ++rowNumber, "M2", "125", 25 );
data.AddRow( ++rowNumber, "M2", "125", 70 );
data.AddRow( ++rowNumber, "M2", "125", 58 );
data.AddRow( ++rowNumber, "M2", "125", 45 );
data.AddRow( ++rowNumber, "M3", "15", 138 );
data.AddRow( ++rowNumber, "M3", "15", 110 );
data.AddRow( ++rowNumber, "M3", "15", 168 );
data.AddRow( ++rowNumber, "M3", "15", 160 );
data.AddRow( ++rowNumber, "M3", "70", 174 );
data.AddRow( ++rowNumber, "M3", "70", 120 );
data.AddRow( ++rowNumber, "M3", "70", 150 );
data.AddRow( ++rowNumber, "M3", "70", 139 );
data.AddRow( ++rowNumber, "M3", "125", 96 );
data.AddRow( ++rowNumber, "M3", "125", 104 );
data.AddRow( ++rowNumber, "M3", "125", 82 );
data.AddRow( ++rowNumber, "M3", "125", 60 );
return data;
}
} // class
} // namespace
← All NMath Code Examples