Monday, August 27, 2012

Running Average and Running Standard Deviation in Java

Today I needed to generate statistics for a simulation in real-time, which forced me to code a class that calculates the running average and running standard deviation of incoming data. I remember doing this a long time ago for another project based on MATLAB, but today I needed a Java implementation. The following code example shows how to calculate the running average and running standard deviation for streaming data. Thanks to Subluminal Messages for the simple math implementation!

The Code

public class RunningStatDemo {

  public static void main(String[] args) {

    RunningStatDemo rsd = new RunningStatDemo();
    rsd.go();
  }

  private void go() {

    RunningStat rs = new RunningStat();
    rs.put(1);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(1);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(10);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(20);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(50);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());

    rs.put(50);
    System.out.println("ave: " + rs.getAverage());
    System.out.println("std: " + rs.getStandardDeviation());
  }

  public class RunningStat {

    private int count = 0;
    private double average = 0.0;
    private double pwrSumAvg = 0.0;
    private double stdDev = 0.0;

    /**
     * Incoming new values used to calculate the running statistics
     * 
     * @param value
     */
    public void put(double value) {

      count++;
      average += (value - average) / count;
      pwrSumAvg += (value * value - pwrSumAvg) / count;
      stdDev = Math.sqrt((pwrSumAvg * count - count * average * average) / (count - 1));

    }

    public double getAverage() {

      return average;
    }

    public double getStandardDeviation() {

      return Double.isNaN(stdDev) ? 0.0 : stdDev;
    }

  }

}

Results

ave: 1.0
std: 0.0
ave: 1.0
std: 0.0
ave: 4.0
std: 5.196152422706632
ave: 8.0
std: 9.055385138137417
ave: 16.4
std: 20.354360712142253
ave: 22.0
std: 22.794736234490628

Piece of Cake!!!

1 comment:

Anonymous said...

Make this more efficient by removing stdDev from the class and calculating the value only when getStandardDeviation() is called. Not need to do all that computation work on every put().