【问题标题】:How to find trend (growth/decrease/stationarity) of a data series如何找到数据系列的趋势(增长/减少/平稳性)
【发布时间】:2019-05-09 08:46:18
【问题描述】:

我正在尝试提取制造机器的OEE 趋势。我已经有一个 OEE 数据集,或多或少每 30 秒为每台制造机器计算并存储在数据库中。

我想做的是提取数据集的一个子集(例如,过去 30 分钟)并说明 OEE 是否增长、降低或稳定(具有一定的阈值)。我的任务不是预测 OEE 的下一个值是多少,而只是知道是否下降(期望的返回值:-1)、增长(期望的返回值:+1)或稳定(期望的返回值:0)基于数据集。我在我的项目中使用Java 8。

这是一个数据集的例子:

71.37
71.37
70.91
70.30
70.30
70.42
70.42
69.77
69.77
69.29
68.92
68.92
68.61
68.61
68.91
68.91
68.50
68.71
69.27
69.26
69.89
69.85
69.98
69.93
69.39
68.97
69.03

从这个数据集中可以看出 OEE 一直在下降(当然基于阈值),因此算法将返回 -1。

我一直在网上搜索没有成功。我找到了this,或this github project,或this stackoverflow question。然而,所有这些都是(或多或少)复杂的预测算法。我正在寻找一个更简单的解决方案。任何帮助都将不胜感激。

【问题讨论】:

  • 更简单的解决方案是什么意思?我可以想到一个非常简单的解决方案 - 比较第一个值和最后一个值(并查看差异是否超过阈值)。
  • 比较第一个和最后一个值不是一个合适的解决方案,因为它没有说明数据系列的趋势。例如,拥有如下数据集:[5, 7, 8, 11, 17, 3],您建议趋势表明 OEE 呈负趋势,而考虑到整个数据集显然是增长趋势.
  • 好的,那么找出每个相邻对之间的差异呢?对于您在评论中的示例,它将是 [2, 3, 3, 6, -14]。并且您检查是否存在比负面差异更多的正面差异?
  • 您如何为看起来像 [5, 6, 7, 8, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5] 的数据集限定趋势?

标签: algorithm analysis trend


【解决方案1】:

您可以获取最后 n 个值的
滑动平均值。
或最后 n 个值的
滑动中位数。

这在很大程度上取决于您的应用程序什么是合适的。但这两者都非常易于实现,并且在很多情况下已经足够好。

【讨论】:

    【解决方案2】:

    正如您从数学中知道的那样,人们会使用 d/dt,这或多或少是在使用步长差异。

    趋势应该有一定的分量。

    class Trend {
        int direction;
        double probability;
    }
    
    Trend trend(double[] lastData) {
        double[] deltas = Arrays.copyOf(lastData, lastData.length - 1);
        for (int i = 0; i < deltas.length; ++i) {
           deltas[i] -= lastData[i + 1];
        }
        // Trend based on two parts:
        int parts = 2;
        int splitN = (deltas.length + 1) / parts;
        int i = 0;
        int[] trends = new int[parts];
        for (int j = 0; j < parts.length; ++j) {
            int n = Math.min(splitN, parts.length - i);
            double partAvg = DoubleStream.of(deltas).skip(i).limit(n).sum() / n;
            trends[j] = tendency(partAvg);
        }
        Trend result = new Trend();
        trend.direction = trends[parts - 1];
        double avg = IntStream.of(trends).average().orElse((double)trend.direction);
        trend.probability = ((direction - avg) + 1) / 2;
        return trends[parts - 1];
    }
    
    int tendency(double sum) {
        final double EPS = 0.0001;
        return sum < -EPS ? -1 : sum > EPS ? 1 : 0;
    }
    

    这不是很复杂。对于更详细的处理,数学论坛可能会很有用。

    【讨论】:

    • 我需要了解double sum = DoubleStream.of(sums).skip(i).limit(n).sum() / n; 行中包含变量sums 的内容
    • 抱歉,sums 应该是 deltas。该表达式计算 deltas[i : i+n] 的平均值
    猜你喜欢
    • 2020-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-03
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 2023-01-14
    相关资源
    最近更新 更多