4
\$\begingroup\$

I changed some methods used previously, and I am wondering if I need to do the multiple for loops over and over again. How do I convert my arrays to lists to use in nested for loops?

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Threading.Tasks;
using TwoWayAnova;

namespace TwoWayAnovaTable
{
public partial class TwoWayAnovaTable : Form
{
    public TwoWayAnovaTable()
    {
        InitializeComponent();
    }

    private static readonly char[] Separators = { ',', ' ' };

private static double _aTreatmentSumOfSquares;
private static double _bTreatmentSumOfSquares;
private static double _interactionSumOfSquares;
    private static double _errorSumOfSquares;
    private static double _sumOfSquares;

    private static double _aMeanTreatmentSumOfSquares;
    private static double _bMeanTreatmentSumOfSquares;
    private static double _interactionMeanSumOfSquares;
    private static double _meanErrorSumOfSquares;

    private static double _aTreatmentDegreesOfFreedom;
    private static double _bTreatmentDegreesOfFreedom;
    private static double _interactionDegreesOfFreedom;
    private static double _errorDegreesOfFreedom;
    private static double _totalDegreesOfFreedom;

    private static double _aTestStatistic;
    private static double _bTestStatistic;
    private static double _interactionTestStatistic;

    private static double _aPValue;
    private static double _bPValue;
    private static double _interactionPValue;


    private static void ProcessFile()
    {
        var lines = File.ReadLines("Data.csv");
        var numbers = ProcessRawNumbers(lines);

        var rowTotal = new List<double>();
        var squareRowTotal = new List<double>();
        var rowMean = new List<double>();
        var totalElements = 0;
        var totalInRow = new List<int>();
        var rowTotalSquareByN = new List<double>();
        var sumOfSquareOfBlock = new List<double>();


        foreach (var values in numbers)
        {
            var sumOfRow = values.Sum();

            rowTotal.Add(sumOfRow);
            squareRowTotal.Add(values.Select(v => v * v).Sum());
            rowMean.Add(sumOfRow / values.Count);
            totalInRow.Add(values.Count);
            totalElements += values.Count;
            rowTotalSquareByN.Add(rowTotal.Select(r => r * r / values.Count).Sum());
            sumOfSquareOfBlock = squareRowTotal - rowTotalSquareByN;
        }

        var grandTotal = rowTotal.Sum();

   }

    int aNum = 3, bNum = 3;

        double[] totalSumPerBlock = new double[bNum];
        double[] totalSumOfSquaresPerBlock = new double[bNum];
        int[] blockTotalElements = new int[bNum];
        double[] totalSquarePerBlockByN = new double[bNum];
        double[] blockMean = new double[bNum];
        double[] sumOfSquaresTotalOfBlock = new double[bNum];


        for (int i = 0; i < bNum; i++)
        {
            for (int j = 0; j < aNum; j++)
            {
                totalSumPerBlock[i] += rowTotal[j + i * 3];
                totalSumOfSquaresPerBlock[i] += squareRowTotal[j + i * 3];
                blockTotalElements[i] += totalInRow[j + i * 3];
                sumOfSquaresTotalOfBlock[i] += sumOfSquareOfBlock[j + i * 3];

            }
            totalSquarePerBlockByN[i] += totalSumPerBlock[i] * totalSumPerBlock[i] / blockTotalElements[i];
            blockMean[i] = totalSumPerBlock[i] / blockTotalElements[i];
        }

        double[] grandTotalAllBlocks = new double[bNum];
        double[] grandBlockSumOfSquares = new double[bNum];
        int[] grandNumberOfElements = new int[bNum];
        double[] grandSumOfSquares = new double[bNum];
        double[] grandBlockSquaresSumByN = new double[bNum];
        double[] grandBlockMean = new double[bNum];

        double finalSum = 0;
        double finalSumOfSquaresRow = 0;
        int finalElements = 0;
        double finalSumOfSquaresByN = 0;
        double finalSumOfSquares = 0;
        double finalMean = 0;

        for (int i = 0; i < bNum; i++)
        {
            for (int j = 0; j < aNum; j++)
            {
                grandTotalAllBlocks[i] += rowTotal[i + 3 * j];
                grandBlockSumOfSquares[i] += squareRowTotal[i + 3 * j];
                grandNumberOfElements[i] += totalInRow[i + 3 * j];
            }
            grandBlockSquaresSumByN[i] = grandTotalAllBlocks[i] * grandTotalAllBlocks[i] / grandNumberOfElements[i];
            grandBlockMean[i] = grandTotalAllBlocks[i] / grandNumberOfElements[i];
            finalSum += grandTotalAllBlocks[i];
            finalSumOfSquaresRow += grandBlockSumOfSquares[i];
            finalElements += grandNumberOfElements[i];
            finalSumOfSquaresByN = finalSum * finalSum / finalElements;
            finalSumOfSquares = finalSumOfSquaresRow - finalSumOfSquaresByN;
            finalMean = finalSum / finalElements;
        }


        for (int i = 0; i < numbers.Count; i++)
        {
            _errorSumOfSquares += sumOfSquareOfBlock[i];
            _interactionSumOfSquares += rowTotalSquareByN[i];
        }

        for (int i = 0; i < bNum; i++)
        {
            _aTreatmentSumOfSquares += totalSquarePerBlockByN[i];
            _bTreatmentSumOfSquares += grandBlockSquaresSumByN[i];
            _interactionSumOfSquares = _interactionSumOfSquares - totalSquarePerBlockByN[i] - grandBlockSquaresSumByN[i];
        }

        _interactionSumOfSquares = (-1) * (_aTreatmentSumOfSquares - _bTreatmentSumOfSquares) + finalSumOfSquaresByN;
        _aTreatmentSumOfSquares -= finalSumOfSquaresByN;
        _bTreatmentSumOfSquares -= finalSumOfSquaresByN;
        _sumOfSquares = _errorSumOfSquares + _bTreatmentSumOfSquares + _interactionSumOfSquares + _aTreatmentSumOfSquares;

        _aTreatmentDegreesOfFreedom = aNum - 1;
        _bTreatmentDegreesOfFreedom = bNum - 1;
        _interactionDegreesOfFreedom = _aTreatmentDegreesOfFreedom * _bTreatmentDegreesOfFreedom;
        _errorDegreesOfFreedom = (totalElements - 1) - _aTreatmentDegreesOfFreedom - _bTreatmentDegreesOfFreedom - _interactionDegreesOfFreedom;
        _totalDegreesOfFreedom = totalElements-1;

        _aMeanTreatmentSumOfSquares = _aTreatmentSumOfSquares / _aTreatmentDegreesOfFreedom;
        _bMeanTreatmentSumOfSquares = _bTreatmentSumOfSquares / _bTreatmentDegreesOfFreedom;
        _interactionMeanSumOfSquares = _interactionSumOfSquares / _interactionDegreesOfFreedom;
        _meanErrorSumOfSquares = _errorSumOfSquares / _errorDegreesOfFreedom;

        _aTestStatistic = TwoWayAnovaClass.CalculateTestStatistic(_aMeanTreatmentSumOfSquares,_meanErrorSumOfSquares);
        _bTestStatistic = TwoWayAnovaClass.CalculateTestStatistic(_bMeanTreatmentSumOfSquares, _meanErrorSumOfSquares);
        _interactionTestStatistic = TwoWayAnovaClass.CalculateTestStatistic(_interactionMeanSumOfSquares, _meanErrorSumOfSquares);

        _aPValue = TwoWayAnovaClass.CalculatePValue(_aTestStatistic, _aTreatmentDegreesOfFreedom, _errorDegreesOfFreedom);
        _bPValue = TwoWayAnovaClass.CalculatePValue(_bTestStatistic, _bTreatmentDegreesOfFreedom, _errorDegreesOfFreedom);
        _interactionPValue = TwoWayAnovaClass.CalculatePValue(_interactionTestStatistic, _interactionDegreesOfFreedom, _errorDegreesOfFreedom);

        TSS = _aTreatmentSumOfSquares.ToString();
        ESS = _errorSumOfSquares.ToString();
        BSS = _bTreatmentSumOfSquares.ToString();
        ISS = _interactionSumOfSquares.ToString();
        TotSS = _sumOfSquares.ToString();

        TDF = _aTreatmentDegreesOfFreedom.ToString();
        BDF = _bTreatmentDegreesOfFreedom.ToString();
        IDF = _interactionDegreesOfFreedom.ToString();
        EDF = _errorDegreesOfFreedom.ToString();
        TotDF = _totalDegreesOfFreedom.ToString();

        TMS = _aMeanTreatmentSumOfSquares.ToString();
        BMS = _bMeanTreatmentSumOfSquares.ToString();
        IMS = _interactionMeanSumOfSquares.ToString();
        EMS = _meanErrorSumOfSquares.ToString();

        FT = _aTestStatistic.ToString();
        FBk = _bTestStatistic.ToString();
        FIn = _interactionTestStatistic.ToString();

        pT = _aPValue.ToString();
        pBl = _bPValue.ToString();
        pI = _interactionPValue.ToString();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        ReadFile();
        display();
    }

    private void display()
    {
        textBoxTSS.Text = TSS;
        textBoxESS.Text = ESS;
        textBoxISS.Text = ISS;
        textBoxBSS.Text = BSS;
        textBoxTotSS.Text = TotSS;
        textBoxTDF.Text = TDF;
        textBoxEDF.Text = EDF;
        textBoxIDF.Text = IDF;
        textBoxBDF.Text = BDF;
        textBoxTotDF.Text = TotDF;
        textBoxTMS.Text = TMS;
        textBoxEMS.Text = EMS;
        textBoxBMS.Text = BMS;
        textBoxIMS.Text = IMS;
        textBoxFT.Text = FT;
        textBoxFB.Text = FBk;
        textBoxFI.Text = FIn;
        textBoxpT.Text = pT;
        textBoxpB.Text = pBl;
        textBoxpI.Text = pI;
    }
}
}
\$\endgroup\$
0

2 Answers 2

6
\$\begingroup\$

First off, add a

using OneWayAnovaClassLibrary;

to the top of your partial class. That way you can change all of the calls from the library from:

OneWayAnovaClassLibrary.OneWayAnova(...)

into:

OneWayAnova(...)

These assignment could also be changed to go right into your static strings.

This line:

static string TSS, ESS, TotSS, TDF, EDF, TotDF, TMS, EMS, F, p;

Should be split into a line per variable. You should also rename the variables to something meaningful:

static string TreatmentSumOfSquares;
static string ErrorSumOfSquares;
...

You need to get more consistent with your use of var vs variable type. My suggestion would be to use var anywhere a variable is assigned within a method.

I would also change the array declarations to List declarations. This will allow you to change a couple of the for(...) loops into foreach(...) loops.

In your library, I'm not sure why you are doing this in your methods:

double errorSumOfSquares = 0;
return errorSumOfSquares = sumOfSquares - treatmentSumOfSquares;

They should be

return sumOfSquares - treatmentSumOfSquares;

You also need to store sumOfSquares somewhere that the other methods will be able to access it. Currently, it is only valid in the method that you are calculating it in.

The method names should be changed to start with a capital letter treatmentSumOfSquares would be TreatmentSumOfSquares etc. This is standard C# naming convention.

Anywhere you have an array passed into a method, change it to IEnumerable.

This is a good start, there are a few more things I see, but they are pretty minor. If you want a full clean up, let me know and I'll add it later.

Good luck.

EDIT:

Here is a first kick at the can for a clean up. I have basically used what Jesse posted for the library, but renamed to methods to portray what they are doing. The way you named them before indicated to me that they were Properties

Code partially cleaned up:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using OneWayAnovaClassLibrary;

namespace OneWayAnovaTable
{
    public class OneWayAnovaTable : Form
    {
        public OneWayAnovaTable()
        {
            InitializeComponent();
        }

        private static readonly char[] Separators = {',', ' '};


        // Not sure why these are static
        // Leaving them because you probably have a reason.
        private static double _treatmentSumOfSquares;
        private static double _errorSumOfSquares;
        private static double _sumOfSquares;
        private static double _meanTreatmentSumOfSquares;
        private static double _meanErrorSumOfSquares;
        private static double _testStatistic;

        // Not sure what these variables represent
        // Rename as appropriate.
        private static double _tdf;
        private static double _edf;
        private static double _totDf;
        private static double _p;

        private static void ProcessFile()
        {
            var lines = File.ReadLines("Data.csv");
            var numbers = ProcessRawNumbers(lines);

            var rowTotal = new List<double>();
            var squareRowTotal = new List<double>();
            var rowMean = new List<double>();
            var totalElements = 0;
            var totalInRow = new List<int>();


            foreach (var values in numbers)
            {
                var sumOfRow = values.Sum();

                rowTotal.Add(sumOfRow);
                squareRowTotal.Add(values.Select(v => v*v).Sum());
                rowMean.Add(sumOfRow/values.Count);
                totalInRow.Add(values.Count);
                totalElements += values.Count;
            }

            var grandTotal = rowTotal.Sum();

            _sumOfSquares = OneWayAnova.CalculateTotalSumOfSquares(squareRowTotal, grandTotal, totalElements);
            _treatmentSumOfSquares = OneWayAnova.CalculateTreatmentSumOfSquares(rowTotal.ToArray(), totalInRow,
                                                                                grandTotal,
                                                                                totalElements);
            _errorSumOfSquares = OneWayAnova.CalculateErrorSumOfSquares(_sumOfSquares, _treatmentSumOfSquares);
            _meanTreatmentSumOfSquares = OneWayAnova.CalculateMeanTreatmentSumOfSquares(_treatmentSumOfSquares,
                                                                                        totalInRow.ToArray());
            _meanErrorSumOfSquares = OneWayAnova.CalculateMeanErrorSumOfSquares(_errorSumOfSquares, (numbers.Count - 1),
                                                                                (totalElements - 1));
            _testStatistic = OneWayAnova.CalculateTestStatistic(_meanTreatmentSumOfSquares, _meanErrorSumOfSquares);
            _p = OneWayAnova.CalculatePValue(_testStatistic, (numbers.Count - 1), (totalElements - (numbers.Count - 1)));

            _tdf = (numbers.Count() - 1);
            _edf = (totalElements - numbers.Count());
            _totDf = (totalElements - 1);
        }

        private static List<List<double>> ProcessRawNumbers(IEnumerable<string> lines)
        {
            var numbers = new List<List<double>>();
            /*System.Threading.Tasks.*/
            Parallel.ForEach(lines, line =>
                                        {
                                            lock (numbers)
                                            {
                                                numbers.Add(ProcessLine(line));
                                            }
                                        });
            return numbers;
        }

        private static List<double> ProcessLine(string line)
        {
            var list = new List<double>();
            foreach (var s in line.Split(Separators, StringSplitOptions.RemoveEmptyEntries))
            {
                double i;
                if (Double.TryParse(s, out i))
                {
                    list.Add(i);
                }
            }
            return list;
        }

        private void button2_Click(object sender, EventArgs e)
        {
            ProcessFile();
            Display();
        }

        private void Display()
        {
            textBoxTSS.Text = _treatmentSumOfSquares.ToString(CultureInfo.InvariantCulture);
            textBoxESS.Text = _errorSumOfSquares.ToString(CultureInfo.InvariantCulture);
            textBoxTotSS.Text = _sumOfSquares.ToString(CultureInfo.InvariantCulture);
            textBoxTDF.Text = _tdf.ToString(CultureInfo.InvariantCulture);
            textBoxEDF.Text = _edf.ToString(CultureInfo.InvariantCulture);
            textBoxTotDF.Text = _totDf.ToString(CultureInfo.InvariantCulture);
            textBoxTMS.Text = _meanTreatmentSumOfSquares.ToString(CultureInfo.InvariantCulture);
            textBoxEMS.Text = _meanErrorSumOfSquares.ToString(CultureInfo.InvariantCulture);
            textBoxF.Text = _testStatistic.ToString(CultureInfo.InvariantCulture);
            textBoxp.Text = _p.ToString(CultureInfo.InvariantCulture);
        }
    }
}

namespace OneWayAnovaClassLibrary
{
    public static class OneWayAnova
    {
        public static double CalculateTotalSumOfSquares(IEnumerable<double> squareRowTotal, double grandTotal,
                                                        int totalOfAllElements)
        {
            return squareRowTotal.Sum() - (grandTotal*grandTotal/totalOfAllElements);
        }

        public static double CalculateTreatmentSumOfSquares(double[] rowTotal, IEnumerable<int> totalInRow,
                                                            double grandTotal,
                                                            int totalOfAllElements)
        {
            return totalInRow.Select((t, i) => rowTotal[i]*rowTotal[i]/t).Sum() -
                   (grandTotal*grandTotal/totalOfAllElements);
        }

        public static double CalculateErrorSumOfSquares(double sumOfSquares, double treatmentSumOfSquares)
        {
            return sumOfSquares - treatmentSumOfSquares;
        }

        public static double CalculateMeanTreatmentSumOfSquares(double errorSumOfSquares, int[] totalInRow)
        {
            return errorSumOfSquares/(totalInRow.Length - 1);
        }

        public static double CalculateMeanErrorSumOfSquares(double errorSumOfSquares, int a, int b)
        {
            return errorSumOfSquares/(b - a);
        }

        public static double CalculateTestStatistic(double meanTreatmentSumOfSquares, double meanErrorSumOfSquares)
        {
            return meanTreatmentSumOfSquares/meanErrorSumOfSquares;
        }

        public static double CalculatePValue(double fStatistic, int degreeNum, int degreeDenom)
        {
            return Integrate(0, fStatistic, degreeNum, degreeDenom);
        }

        // As it stands, this can be made private
        public static double Integrate(double start, double end, int degreeFreedomT, int degreeFreedomE)
        {
            const int Iterations = 100000;
            double x, sum = 0, sumT = 0;
            var dist = (end - start)/Iterations;

            for (var i = 1; i < Iterations; i++)
            {
                x = start + (i*dist);
                sumT += IntegralFunction(x - (dist/2), degreeFreedomT, degreeFreedomE);
                sum += IntegralFunction(x, degreeFreedomT, degreeFreedomE);
            }

            x = start + (Iterations*dist);
            sumT += IntegralFunction(x - (dist/2), degreeFreedomT, degreeFreedomE);
            return (dist/6)*
                   (IntegralFunction(start, degreeFreedomT, degreeFreedomE) +
                    IntegralFunction(end, degreeFreedomT, degreeFreedomE) + (2*sum) + (4*sumT));
        }

        // As it stands, this can be made private
        public static double IntegralFunction(double x, int degreeFreedomT, int degreeFreedomE)
        {
            return ((Math.Pow(degreeFreedomE, degreeFreedomE/2.0)*Math.Pow(degreeFreedomT, degreeFreedomT/2.0))/
                    (Factorial((degreeFreedomE/2) - 1)*Factorial((degreeFreedomT/2) - 1)))*
                   Factorial((((degreeFreedomT + degreeFreedomE)/2) - 1))*
                   (Math.Pow(x, (degreeFreedomE/2) - 1)/
                    Math.Pow((degreeFreedomT + (degreeFreedomE*x)), ((degreeFreedomE + degreeFreedomT)/2.0)));
        }

        // As it stands, this can be made private
        public static double Factorial(double n)
        {
            return n.Equals(0) ? 1.0 : n * Factorial(n - 1);
        }
    }
}
\$\endgroup\$
6
  • \$\begingroup\$ I would love a full clean up, if you don't mind posting it. Also, I am not very comfortable using IEnumerable, in the sense, I find it confusing implementing, though it is a powerful tool. Would you please show how to use it in the methods correctly? Thank you for your time. \$\endgroup\$ Aug 2, 2012 at 15:32
  • \$\begingroup\$ I am using static, because the tutorial I started learning from used static for my data and methods. What do you recommend using, as I will be having return values? \$\endgroup\$ Aug 3, 2012 at 5:45
  • \$\begingroup\$ +1, but I wouldn't go so far as saying My suggestion would be to use var _anywhere_ a variable is assigned within a method.. \$\endgroup\$
    – ANeves
    Aug 3, 2012 at 8:04
  • 1
    \$\begingroup\$ @CamelUno static is a keyword that makes the instances the same across all instances of this class. So if you have class objA, objB, objC and have a static prop = 3, prop will have the same value across all the instances. Now if you took the static off, each instance could be assigned a different value for prop, so you could have objA.Prop = 1, objB.Prop = 2 and objC.Prop = 3. Like I said, I'm not too worried about it because I don't know enough on how this class is going to be used. Maybe take a read Here \$\endgroup\$ Aug 3, 2012 at 14:11
  • \$\begingroup\$ @ANeves I see your point, and there are discussions all over about it, with people on both sides. Personally, I prefer to use var, but I see the value of implicitly declaring with the type. \$\endgroup\$ Aug 3, 2012 at 14:14
5
\$\begingroup\$

Here's a take on it (note it uses LINQ to simplify a bit). There's a few other potential improvements (such as removing the file reading from the UI class and putting it in its own, etc.) but I just opted to clean up the existing code a bit:

Program for button and Function calling is here:

namespace OneWayAnovaTable
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.Threading.Tasks;
    using System.Windows.Forms;

    using OneWayAnovaClassLibrary;

    public partial class OneWayAnovaTable : Form
    {
        private string tss, ess, totSs, tdf, edf, totDf, tms, ems, f, p;

        public OneWayAnovaTable()
        {
            this.InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            this.ReadFile();
            this.Display();
        }

        private void ReadFile()
        {
            var lines = File.ReadLines("Data.csv");
            var numbers = new List<List<double>>();
            var separators = new[] { ',', ' ' };
            /*System.Threading.Tasks.*/
            Parallel.ForEach(lines, line =>
            {
                var list = new List<double>();
                foreach (var s in line.Split(separators, StringSplitOptions.RemoveEmptyEntries))
                {
                    double i;

                    if (double.TryParse(s, out i))
                    {
                        list.Add(i);
                    }
                }

                lock (numbers)
                {
                    numbers.Add(list);
                }
            });

            var rowTotal = new double[numbers.Count];
            var squareRowTotal = new double[numbers.Count];
            var rowMean = new double[numbers.Count];
            var totalElements = 0;
            var totalInRow = new int[numbers.Count()];
            ////var grandTotalMean = 0.0;
            ////var grandMean = 0.0;

            for (var row = 0; row < numbers.Count; row++)
            {
                var values = numbers[row].ToArray();

                rowTotal[row] = values.Sum();
                squareRowTotal[row] = values.Select(v => v * v).Sum();
                rowMean[row] = rowTotal[row] / values.Length;
                totalInRow[row] += values.Length;
                totalElements += totalInRow[row];
                ////grandTotalMean += rowMean[row];
                ////grandMean += rowMean[row] / numbers.Count;
            }

            var grandTotal = rowTotal.Sum();

            var sumOfSquares = OneWayAnova.TotalSumOfSquares(squareRowTotal, grandTotal, totalElements);
            var treatmentSumOfSquares = OneWayAnova.TreatmentSumOfSquares(rowTotal, totalInRow, grandTotal, totalElements);
            var errorSumOfSquares = OneWayAnova.ErrorSumOfSquares(sumOfSquares, treatmentSumOfSquares);
            var meanTreatmentSumOfSquares = OneWayAnova.MeanTreatmentSumOfSquares(treatmentSumOfSquares, totalInRow);
            var meanErrorSumOfSquares = OneWayAnova.MeanErrorSumOfSquares(errorSumOfSquares, (numbers.Count - 1), (totalElements - 1));
            var fStatistic = OneWayAnova.TestStatistic(meanTreatmentSumOfSquares, meanErrorSumOfSquares);
            var pValue = OneWayAnova.pValue(fStatistic, (numbers.Count - 1), (totalElements - (numbers.Count - 1)));

            this.tss = treatmentSumOfSquares.ToString();
            this.ess = errorSumOfSquares.ToString();
            this.totSs = sumOfSquares.ToString();
            this.tdf = (numbers.Count() - 1).ToString();
            this.edf = (totalElements - numbers.Count()).ToString();
            this.totDf = (totalElements - 1).ToString();
            this.tms = meanTreatmentSumOfSquares.ToString();
            this.ems = meanErrorSumOfSquares.ToString();
            this.f = fStatistic.ToString();
            this.p = pValue.ToString();
        }

        private void Display()
        {
            this.textBoxTSS.Text = this.tss;
            this.textBoxESS.Text = this.ess;
            this.textBoxTotSS.Text = this.totSs;
            this.textBoxTDF.Text = this.tdf;
            this.textBoxEDF.Text = this.edf;
            this.textBoxTotDF.Text = this.totDf;
            this.textBoxTMS.Text = this.tms;
            this.textBoxEMS.Text = this.ems;
            this.textBoxF.Text = this.f;
            this.textBoxp.Text = this.p;
        }
    }
}

The Library file with all the functions is here:

namespace OneWayAnovaClassLibrary
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public static class OneWayAnova
    {
        public static double TotalSumOfSquares(IEnumerable<double> squareRowTotal, double grandTotal, int totalOfAllElements)
        {
            return squareRowTotal.Sum() - (grandTotal * grandTotal / totalOfAllElements);
        }

        public static double TreatmentSumOfSquares(double[] rowTotal, IEnumerable<int> totalInRow, double grandTotal, int totalOfAllElements)
        {
            return totalInRow.Select((t, i) => rowTotal[i] * rowTotal[i] / t).Sum() - (grandTotal * grandTotal / totalOfAllElements);
        }

        public static double ErrorSumOfSquares(double sumOfSquares, double treatmentSumOfSquares)
        {
            return sumOfSquares - treatmentSumOfSquares;
        }

        public static double MeanTreatmentSumOfSquares(double errorSumOfSquares, int[] totalInRow)
        {
            return errorSumOfSquares / (totalInRow.Length - 1);
        }

        public static double MeanErrorSumOfSquares(double errorSumOfSquares, int a, int b)
        {
            return errorSumOfSquares / (b - a);
        }

        public static double TestStatistic(double meanTreatmentSumOfSquares, double meanErrorSumOfSquares)
        {
            return meanTreatmentSumOfSquares / meanErrorSumOfSquares;
        }

        public static double pValue(double fStatistic, int degreeNum, int degreeDenom)
        {
            return Integrate(0, fStatistic, degreeNum, degreeDenom);
        }

        public static double Integrate(double start, double end, int degreeFreedomT, int degreeFreedomE)
        {
            const int Iterations = 100000;
            double x, sum = 0, sumT = 0;
            var dist = (end - start) / Iterations;

            for (var i = 1; i < Iterations; i++)
            {
                x = start + (i * dist);
                sumT += IntegralFunction(x - (dist / 2), degreeFreedomT, degreeFreedomE);
                sum += IntegralFunction(x, degreeFreedomT, degreeFreedomE);
            }

            x = start + (Iterations * dist);
            sumT += IntegralFunction(x - (dist / 2), degreeFreedomT, degreeFreedomE);
            return (dist / 6) * (IntegralFunction(start, degreeFreedomT, degreeFreedomE) + IntegralFunction(end, degreeFreedomT, degreeFreedomE) + (2 * sum) + (4 * sumT));
        }

        public static double IntegralFunction(double x, int degreeFreedomT, int degreeFreedomE)
        {
            return ((Math.Pow(degreeFreedomE, degreeFreedomE / 2.0) * Math.Pow(degreeFreedomT, degreeFreedomT / 2.0)) / (Factorial((degreeFreedomE / 2) - 1) * Factorial((degreeFreedomT / 2) - 1))) * Factorial((((degreeFreedomT + degreeFreedomE) / 2) - 1)) * (Math.Pow(x, (degreeFreedomE / 2) - 1) / Math.Pow((degreeFreedomT + (degreeFreedomE * x)), ((degreeFreedomE + degreeFreedomT) / 2.0)));
        }

        public static double Factorial(double n)
        {
            return n == 0 ? 1.0 : n * Factorial(n - 1);
        }
    }
}

The entry point is in another program as follows:

namespace OneWayAnovaTable
{
    using System;
    using System.Windows.Forms;

    /// <summary>
    /// Holds the main entry point for the application.
    /// </summary>
    internal static class Program
    {
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        private static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            using (var tempObj = new OneWayAnovaTable())
            {
                tempObj.ShowDialog();
            }
        }
    }
}
\$\endgroup\$
2
  • \$\begingroup\$ Yes, this is a lot cleaner, and you have done a great job given what you had to work with, but this can be taken further. Functions can be shorter, a lot more work can be outsourced to a class that is not responsible for GUI, and the Display method can be fed a single object which contains tss through p as readonly properties with more descriptive names. That said, the original computation is a bit hard to follow without understanding the domain. \$\endgroup\$
    – Leonid
    Aug 10, 2012 at 21:58
  • \$\begingroup\$ Oh, I agree fully. Hence my opening statement in which I deliberately limit myself to the immediate possibilities :) \$\endgroup\$ Aug 11, 2012 at 13:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.