b1uceree wrote:
Hi, still very new to programming but am a little stumped by how to do this
idea i have.
I need to make a moving average which takes every nth value in a data series
to build a running total which can then be divided by the length of the
moving average. The data series will be gaining a new value every x amount of
time t so the average has to be made from the last added value.
If you want the moving average to be exactly the average of the last N
samples, you need to save N samples, dropping one off the end when you
add a new one to the beginning.
For example:
const int kcvalueMoving = 20;
double valueTotal = 0;
Queue<doublevaluesPrevious = new Queue<double>(kcvalueMoving);
double MovingAverage(double valueNew)
{
if (valuesPrevious.Count == kcvalueMoving)
{
valueTotal -= valuesPrevious.Dequeue();
}
valueTotal += valueNew;
valuesPrevious.Enqueue(valueNew);
return valuesTotal / valuesPrevious.Count;
}
If you don't want to keep track of all the previous values, you can just
keep the sum, adding a weighted value to it with each iteration. As
each iteration weights the previous sum at less than 100%, trailing
values will become less and less significant. However, it's not exactly
a moving average and you'll have to watch out for the divisor (count of
samples) eventually reaching the maximum the variable can contain.
IMHO, if you want a true moving average, the code above is probably want
you want.
And i also
need a way to use this same moving average but from different start point ie
t-1, t-2 etc What is the best way to do this?
I'm not exactly clear on this part of your requirement. If you have to
be able to arbitrarily pick any point in the sequence of data and return
a moving average based on that sequence, you will have to save _all_ of
the samples in the sequence of data, and then simply perform a regular
average of the previous N elements for a given position within the sequence.
If you have this requirement and the number of samples for a given
moving average is relatively small (less than a hundred or so, for
example), then you may not want to bother with the implementation I
included above. It's slower to recalculate the average from scratch
each time, but if you have to do that anyway in some cases, you might as
well keep the code simple and just have a single implementation that
works for both scenarios.
If you have a known subset of "different start points", then you could
just cache the result of the primary moving average calculation. For
example, if you always only want to allow access to the last M averages,
you could keep a list of length M. There are a number of ways you could
implement this while allowing both easy adding of new averages and
removal of old ones, while still having access to all of the averages:
* You could use an actual LinkedList and enumerate when you need a
specific entry,
* You could use the Queue class and use the ToArray() to get at a
specific entry within the Queue, or
* You could use a different queue implementation (Jon Skeet has a
RandomAccessQueue that would serve this purpose nicely, in his MiscUtil
library:
http://www.yoda.arachsys.com/csharp/miscutil/)
If you mean something different, then perhaps you could clarify.
Pete