Averaging initial values for rolling series

Posted by Dave Jarvis on Stack Overflow See other posts from Stack Overflow or by Dave Jarvis
Published on 2010-03-23T18:13:01Z Indexed on 2010/03/23 18:13 UTC
Read the original article Hit count: 385

Filed under:
|
|
|

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:

© Stack Overflow or respective owner

Related posts about Trends

Related posts about java