Home > Mobile >  Variance and Average on a 2D array in C#
Variance and Average on a 2D array in C#

Time:07-03

I was reading this article and I trying to follow their code example but I think I am missing a library.

They have this :

First, let's create a 2D matrix with some random data. We'll use the System.Random class to generate pseudo-random numbers:

var rand = new Random();

var matrix = new double[5, 5];

for (int i = 0; i < matrix.GetLength(0); i  )
{
    for (int j = 0; j < matrix.GetLength(1); j  )
    {
        matrix = rand.NextDouble() * 100;
    }
}

Now that we have our data, we can calculate the mean and standard deviation:

  double mean = matrix.Average();
  double stdDev = Math.Sqrt(matrix.Variance());

but when I tried that in C# does, I get this compile time error:

Severity Code Description Project File Line Suppression State Error CS1061 'double[,]' does not contain a definition for 'Variance' and no accessible extension method 'Variance' accepting a first argument of type 'double[,]' could be found (are you missing a using directive or an assembly reference?)

I tried adding

using System.Numerics;

but it did not help

CodePudding user response:

In case you want to apply Linq method to 2D array T[,] items, you can use OfType() (or Cast<T>()) to obtain a enumeration IEnumeration<T>. For instance, in your case with Average() you can put it as

using System.Linq;

...

var matrix = new double[5,5];

...

double mean = matrix
  .OfType<double>() 
  .Average();

Since standard Linq doesn't have (at least in .Net 6) Variance method, we should do a simple statistics. Having a sequence of x = {x_1, x_2, x_3, ..., x_N} of N items the variance will be

Var(x) = Sum(x * x) / N - Sum(x) * Sum(x) / N / N

In our case it can be a simple Aggregate:

// Let's compute all required statistics 
//   n  - number of items
//   s  - sum of items
//   s  - sum of items squared
// in one go with a help of Aggregate 
var stat = matrix
 .OfType<double>()
 .Aggregate((n: 0, s: 0.0, ss: 0.0), (s, a) => (s.n   1, s.s   a, s.ss   a * a));

double stdDev = Math.Sqrt(stat.ss / stat.n - stat.s * stat.s / stat.n / stat.n); 

In order not to deal with such constructions, you can implement extension methods:

public static partial class Array2dExtensions {
  public static double Average(this double[,] matrix) {
    if (matrix == null)
      throw new ArgumentNullException(nameof(matrix));

    return matrix
      .OfType<double>() 
      .Average();
  }

  public static double Variance(this double[,] matrix) {
    if (matrix == null)
      throw new ArgumentNullException(nameof(matrix));

     var stat = matrix
       .OfType<double>()
       .Aggregate((n: 0, s: 0.0, ss: 0.0), (s, a) => 
                  (s.n   1, s.s   a, s.ss   a * a));

     return stat.ss / stat.n - stat.s * stat.s / stat.n / stat.n; 
  }
}

Having this implemented you can put it as if array has Average and Variance methods:

double mean = matrix.Average();
double stdDev = Math.Sqrt(matrix.Variance());
  • Related