java - 使用 Apache Commons Math DescriptiveStatistics 跟踪多个移动平均线

标签 java statistics apache-commons metrics usage-statistics

我正在使用 DescriptiveStatistics跟踪某些指标的移动平均值。我有一个线程每分钟提交一次指标值,我使用 DescriptiveStatistics 上的 setWindowSize(10) 方法跟踪指标的 10 分钟移动平均值。

这适用于跟踪单个移动平均线,但实际上我需要跟踪多个移动平均线,即 1 分钟平均线、5 分钟平均线和 10 分钟平均线。

目前我有以下选择:

  1. 有 3 个不同的 DescriptiveStatistics 实例和 3 个不同的窗口。然而,这意味着我们多次存储原始指标,这并不理想。

  2. 有 1 个 DescriptiveStatistics 实例,并在查询移动平均线时执行类似以下操作:

    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();
    

但是,选项 2 意味着每次查询窗口小于 DescriptiveStats 窗口大小的移动平均线时,我都必须重新计算一堆平均值。

有没有更好的方法?我想存储 1 个指标数据副本,并以不同的时间间隔连续计算它的 N 个移动平均值。这可能会进入 Codahale Metrics 或 Netflix Servo 领域,但我不想为此使用重量级库。

最佳答案

您可以使用 StatUtils 实用程序类并在添加新值时管理数组。一种替代方法是使用 Apache CommonsCircularFifoQueue大小为 10 和 Apache Utils 以简化原始值数组的转换。

您可以在 User Guide 中找到 StatUtils 的示例,以下将与您的用例类似。

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);

关于java - 使用 Apache Commons Math DescriptiveStatistics 跟踪多个移动平均线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43420275/

相关文章:

Java - JSON 输出并不像控制台所建议的那样

java - 如何将下面的示例转换为实现 Runnable 接口(interface)并重写 run 方法

java - 如何通过 https 启动 java servlet?

ruby - 如何衡量点击率的统计显着性?

performance - 如何避免人们将我的代码用于邪恶?

java - Tomcat 7 生产服务器上的 VerifyError 可能由 Apache Commons Logging 1.0.4 引起

java - 如何将文件从 Java servlet 上传到 Tomcat/webapps 中 Web 服务器上的某个位置

java - 地牢生成方法

java - 有没有办法使用 postgresql 执行学生 t 检验

android - org.apache.http 导入在更新到 Android M 后停止工作