I would like to compute the average or sum or another method over elements in an array of values(doubles) conditional on a second array with same length.
For instance, I have a sorted array with dates (double[]dts) and now I would like to compute the average between start date (std) and end date (edd) over the value array (double[]vals) (which is simple and what my code below does).
But if I want to compute e.g. the average of all Mondays in a year the code below doesnt work any more. Any ideas? Thanks!
public static double aggr(double[] dts, double[] vals, double std, double edd)
{
int stdindex = 0;
int eddindex = dts.Length;
for (int k = 0; k < dts.Length; k++)
{
if (dts[k] == std)
{
stdindex = k;
}
if (dts[k] == edd)
{
eddindex = k;
}
}
return vals.Skip(stdindex).Take(eddindex-stdindex).Average();
}
THANKS everybody. I think all answers work. Here is my new code:
public static double aggr(double[] dts, double[] vals, double std, double edd, string peakoffpeakbase, double sumavg)
{
double result;
if (sumavg == 1)
{
if (peakoffpeakbase=="Peak")
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std & dv.d < edd & DateTime.FromOADate(dv.d).DayOfWeek != DayOfWeek.Saturday & DateTime.FromOADate(dv.d).DayOfWeek != DayOfWeek.Sunday & DateTime.FromOADate(dv.d).Hour > 7 & DateTime.FromOADate(dv.d).Hour < 20))
.Select(dv => dv.v).Sum();
}
else if (peakoffpeakbase=="Offpeak")
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std & dv.d < edd & DateTime.FromOADate(dv.d).DayOfWeek == DayOfWeek.Saturday | DateTime.FromOADate(dv.d).DayOfWeek == DayOfWeek.Sunday | DateTime.FromOADate(dv.d).Hour < 8 | DateTime.FromOADate(dv.d).Hour > 19))
.Select(dv => dv.v).Sum();
}
else
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std && dv.d < edd))
.Select(dv => dv.v).Sum();
}
}
else
{
if (peakoffpeakbase == "Peak")
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std & dv.d < edd & DateTime.FromOADate(dv.d).DayOfWeek != DayOfWeek.Saturday & DateTime.FromOADate(dv.d).DayOfWeek != DayOfWeek.Sunday & DateTime.FromOADate(dv.d).Hour > 7 & DateTime.FromOADate(dv.d).Hour < 20))
.Select(dv => dv.v).Average();
}
else if (peakoffpeakbase == "Offpeak")
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std & dv.d < edd & (DateTime.FromOADate(dv.d).DayOfWeek == DayOfWeek.Saturday | DateTime.FromOADate(dv.d).DayOfWeek == DayOfWeek.Sunday | DateTime.FromOADate(dv.d).Hour < 8 | DateTime.FromOADate(dv.d).Hour > 19)))
.Select(dv => dv.v).Average();
}
else
{
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d >= std && dv.d < edd))
.Select(dv => dv.v).Average();
}
}
return result;
}
Obviously this is terrible and very verbose. What I would really like to do is combine the answers below and write sth like:
result = dts.Zip(vals, (d, v) => new { d, v })
.Where(dv => (dv.d.InTimeRange(std,edd).IsBusinessHour(peakoffpeakbase))
.Select(dv => dv.v).CustomX(indicator);
Where InTimeRange and IsBusinessHour are extension methods as described below and customX would take an argument and then either average, sum or do sth else. However I cant get that to work. Thanks again!