Averaging initial values for rolling series
- by Dave Jarvis
Question
Given a maximum sliding window size of 40 (i.e., the set of numbers in the list cannot exceed 40), what is the calculation to ensure a smooth averaging transition as the set size grows from 1 to 40?
Problem Description
Creating a trend line for a set of data has skewed initial values. The complete set of values is unknown at runtime: they are provided one at a time. It seems like a reverse-weighted average is required so that the initial values are averaged differently.
In the image below the leftmost data for the trend line are incorrectly averaged.
Current Solution
Created a new type of ArrayList subclass that calculates the appropriate values and ensures its size never goes beyond the bounds of the sliding window:
/**
* A list of Double values that has a maximum capacity enforced by a sliding
* window. Can calculate the average of its values.
*/
public class AveragingList
extends ArrayList<Double> {
private float slidingWindowSize = 0.0f;
/**
* The initial capacity is used for the sliding window size.
* @param slidingWindowSize
*/
public AveragingList( int slidingWindowSize ) {
super( slidingWindowSize );
setSlidingWindowSize( ( float )slidingWindowSize );
}
public boolean add( Double d ) {
boolean result = super.add( d );
// Prevent the list from exceeding the maximum sliding window size.
//
if( size() > getSlidingWindowSize() ) {
remove( 0 );
}
return result;
}
/**
* Calculate the average.
*
* @return The average of the values stored in this list.
*/
public double average() {
double result = 0.0;
int size = size();
for( Double d: this ) {
result += d.doubleValue();
}
return (double)result / (double)size;
}
/**
* Changes the maximum number of numbers stored in this list.
*
* @param slidingWindowSize New maximum number of values to remember.
*/
public void setSlidingWindowSize( float slidingWindowSize ) {
this.slidingWindowSize = slidingWindowSize;
}
/**
* Returns the number used to determine the maximum values this list can
* store before it removes the first entry upon adding another value.
* @return The maximum number of numbers stored in this list.
*/
public float getSlidingWindowSize() {
return slidingWindowSize;
}
}
Resulting Image
Example Input
The data comes into the function one value at a time. For example, data points (Data) and calculated averages (Avg) typically look as follows:
Data: 17.0
Avg : 17.0
Data: 17.0
Avg : 17.0
Data: 5.0
Avg : 13.0
Data: 5.0
Avg : 11.0
Related Sites
The following pages describe moving averages, but typically when all (or sufficient) data is known:
http://www.cs.princeton.edu/introcs/15inout/MovingAverage.java.html
http://stackoverflow.com/questions/2161815/r-zoo-series-sliding-window-calculation
http://taragana.blogspot.com/
http://www.dreamincode.net/forums/index.php?showtopic=92508
http://blogs.sun.com/nickstephen/entry/dtrace_and_moving_rolling_averages