Track multiple moving averages with Apache Commons Math DescriptiveStatistics

匿名 (未验证) 提交于 2019-12-03 01:05:01

问题:

I am using DescriptiveStatistics to track the moving average of some metrics. I have a thread that submits the metric value every minute, and I track the 10 minute moving average of the metric by using the setWindowSize(10) method on DescriptiveStatistics.

This works fine for tracking a single moving average but I actually need to track multiple moving averages, i.e. the 1 minute average, the 5 minute average, and the 10 minute average.

Currently I have the following options:

  1. Have 3 different DescriptiveStatistics instances with 3 different windows. However, this means we store the raw metrics multiple times which is not ideal.

  2. Have 1 instance of DescriptiveStatistics and do something like the following when querying for a moving average:

    int minutes = <set from parameter>; DescriptiveStatistics stats = <class variable>;  if (minutes == stats.getN()) return stats.getMean(); SummaryStatistics subsetStats = new SummaryStatistics(); for (int i = 0; i < minutes; i++) {     subsetStats.addValue(stats.getElement((int)stats.getN() - i - 1)); } return subsetStats.getMean(); 

However, option 2 means that I have to re-compute a bunch of averages every time I query for a moving average whose window is smaller than the DescriptiveStats window size.

Is there a way to do this better? I want to store 1 copy of the metrics data and continually calculate N moving averages of it with different intervals. This might be getting into the land of Codahale Metrics or Netflix Servo, but I don't want to have to use a heavyweight library just for this.

回答1:

You could use StatUtils utility class and manage the array when adding new values. One alternative is to use CircularFifoQueue of Apache Commons with a size of 10 and Apache Utils to simplify the conversion to array of primitive values.

You can find an example of StatUtils in the User Guide, the following would be something similar to your use case.

CircularFifoQueue<Double> queue = new CircularFifoQueue<>(10);  // Add your values  double[] values = ArrayUtils.toPrimitive(queue.toArray(new Double[0])) mean1 = StatUtils.mean(values, 0, 1); mean5 = StatUtils.mean(values, 0, 5); mean10 = StatUtils.mean(values, 0, 10); 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!