I have multiple input arrays of Float
all of equal size and a single dimension. I want to create a single output Array that contains the average of all the input arrays.
e.g.
//input arrays
float[] array1 = new float[] { 1, 1, 1, 1 };
float[] array2 = new float[] { 2, 2, 2, 2 };
float[] array3 = new float[] { 3, 3, 3, 3 };
float[] array4 = new float[] { 4, 4, 4, 4 };
//the output should be
float[2.5, 2.5, 2.5, 2.5]
I would also like to calculate the standard deviation of the input arrays to.
What is the fastest approach to do this task?
Thanks in advance. Pete
This anwer details how to use LINQ to achieve the goal, with maximum reusability and versatility as the major objective.
Take 1 (package LINQ into a method for convenience)
Take this method:
float[] ArrayAverage(params float[][] arrays)
{
// If you want to check that all arrays are the same size, something
// like this is convenient:
// var arrayLength = arrays.Select(a => a.Length).Distinct().Single();
return Enumerable.Range(0, arrays[0].Length)
.Select(i => arrays.Select(a => a.Skip(i).First()).Average())
.ToArray();
}
It works by taking the range [0..arrays.Length-1]
and for each number i
in the range it calculates the average of the i
th element of each array. It can be used very conveniently:
float[] array1 = new float[] { 1, 1, 1, 1 };
float[] array2 = new float[] { 2, 2, 2, 2 };
float[] array3 = new float[] { 3, 3, 3, 3 };
float[] array4 = new float[] { 4, 4, 4, 4 };
var averages = ArrayAverage(array1, array2, array3, array4);
This can already be used on any number of arrays without modification. But you can go one more step and do something more general.
Take 2 (generalizing for any aggregate function)
float[] ArrayAggregate(Func<IEnumerable<float>, float> aggregate, params float[][] arrays)
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => aggregate(arrays.Select(a => a.Skip(i).First())))
.ToArray();
}
This can be used to calculate any aggregate function:
var output = ArrayAggregate(Enumerable.Average, array1, array2, array3, array4);
Instead of Enumerable.Average
you can substitute any method, extension method, or anonymous function -- which is useful, as there's no built-in standard deviation aggregate function and also this way the ArrayAggregate
function is very versatile. But we can still do better.
Take 3 (generalizing for any aggregate function and any type of array)
We can also make a generic version that works with any built-in type:
T[] ArrayAggregate<T>(Func<IEnumerable<T>, T> aggregate, params T[][] arrays)
{
return Enumerable.Range(0, arrays[0].Length)
.Select(i => aggregate(arrays.Select(a => a.Skip(i).First())))
.ToArray();
}
As you can probably tell, this is not the fastest code to do the job. If your program spends all day calculating averages, use something more close to the metal. However, if you want reusability and versatility I don't think you can do much better than the above.
The fastest way in terms of performance, unless you'd like to unroll the for loop is
float[] sums = new float[4];
for(int i = 0; i < 4; i++)
{
sums[i] = (array1[i]+ array2[i] + array3[i] + array4[i])/4;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With