代码之家  ›  专栏  ›  技术社区  ›  drudge

如何找到潮汐数据的所有波峰和波谷?

  •  4
  • drudge  · 技术社区  · 14 年前

    $data = array('date' => array('time' => array('predicted','observed')));
    

    以下是我正在使用的真实数据示例: http://pastebin.com/raw.php?i=bRc2rmpG

    这是我试图找到高/低值: http://pastebin.com/8PS1frc0

    • 当读数波动时(如 11/14/2010=>11:30:00 11/14/2010=>11:54:00

    注: 我的方法很特别。。我假设我不需要任何可怕的数学东西,因为我不想找到任何平均值,近似值,或未来的估计。我非常欣赏一个更好方法的代码示例,即使它意味着扔掉我迄今为止编写的代码。

    7 回复  |  直到 14 年前
        1
  •  2
  •   Roman Holzner    10 年前

    我想你是在寻找局部极小值和最大值。这很容易做到:

    <?php
    
    $data = array(1, 9, 4, 5, 6, 9, 9, 1);
    
    function minima($data, $radius = 2)
    {
      $minima = array();
    
      for ($i = 0; $i < count($data); $i += $radius)
      {
        $minima[] = min(array_slice($data, $i, $radius));
      }
    
      return $minima;
    }
    
    function maxima($data, $radius = 2)
    {
      $maxima = array();
    
      for ($i = 0; $i < count($data); $i += $radius)
      {
        $maxima[] = max(array_slice($data, $i, $radius));
      }
    
      return $maxima;
    }
    
    print_r(minima($data));
    print_r(maxima($data));
    
    ?>
    

    $radius 并找到该段的最小值。对整个数据集重复此过程。

    注意半径:通常,您希望选择半径作为数据从峰值到波谷的平均距离,但您必须手动查找。它被默认为 2 2个 ,这可能会对您的数据集产生误报。 明智地选择半径。

    祝你好运!

        2
  •  3
  •   Throwback1986    14 年前

    我不得不在嘈杂的生理数据上执行类似的任务。在我看来,你有信号调节问题。这是一个对我有效的过程。

    1. 使用一个滑动窗口(比如10个宽度点)平滑生成的X和Y数组。在此步骤中,您还可以考虑使用冗余和/或伪造的时间戳筛选数据。
    2. 通过比较平滑的Y[1]和Y[0]来执行指示相位检测。与上面的帖子类似,如果(Y[1]>Y[0]),则可以假设数据正在攀升到峰值。如果(Y[1]<Y[0]),则可以假设数据正在下降到谷底。
    3. 通过考虑滑动窗口大小(以补偿滑动窗口导致的“信号滞后”),可以将平滑的X值投影回原始X数据,从而估计峰值/波谷时间。生成的时间值(以秒为单位)可以转换回HH:MM:SS格式进行报告。
        3
  •  1
  •   Emil H    14 年前

    我还没有详细阅读,但你的方法似乎很特别。一个更正确的方法可能是将它与函数相匹配

     f(A,B,w,p;t)=Asin(wt+p)+B 
    

    使用诸如 non-linear least squares

    t = (pi(1+2n)-2p)/w
    

    但我想,如果你的代码真的实现了你想要的,那就没有必要把事情复杂化。别再自寻烦恼了。:)

        4
  •  1
  •   Lucas Moeskops    14 年前

    • 只有当至少接下来的两个条目也在同一方向时,才更改方向。

    • 不要让数据在太小的差异上做出决定。扔掉无关紧要的数字。如果你说 $error = 0.10; if $previous - $error > $current 等等。

        5
  •  0
  •   Marc B    14 年前

    峰谷探测必须有多精确?如果你只需要找到峰谷出现的确切记录,难道不足以检查拐点吗?

    e、 g.考虑到在位置“i”的记录,如果记录[i-1]和记录[i+1]都比记录[i]高,那么就有一个山谷。如果记录[i-1]和记录[i+1]都比记录[i]低,就有一个峰值。只要你的采样率比潮汐变化快(向上看 Nyquist frequency ),这个过程应该能让你得到数据的峰值/谷。

    如果您需要从中生成一个图表,并尝试为波峰/波谷外推更精确的时间点,那么您需要做更多的工作。

        6
  •  0
  •   lijie    14 年前

    一种方法可以是定义绝对或相对偏差过去,你将进一步的峰/槽分类为新的峰/槽,而不是在现有的峰/谷周围波动。

    目前, $direction 确定是否正在查找峰值或波谷,因此,在导数符号发生变化时,不必转换到其他状态(查找波谷或波谷),而是仅当与当前峰值/波谷的偏差“足够大”时,才可以考虑更改状态。

        7
  •  0
  •   BCS    14 年前

    考虑到你不应该在12小时内看到两个最大值或2分钟,一个简单的解决方法是使用一个3-5小时左右的滑动窗口来找到最大值和最小值。如果它最终在第一个或最后30分钟内出现,请忽略它。

    例如,给定以下数据:

    1 2 3 4 5 6 5 6 7 8 7 6 5 4 3 2 1 2
    

    1 2 | 3 4 5 6 | 5 6,  max = 6, ignore = Y
    2 3 | 4 5 6 5 | 6 7,  max = 7, ignore = Y
    3 4 | 5 6 5 6 | 7 8,  max = 8, ignore = Y
    4 5 | 6 5 6 7 | 8 7,  max = 8, ignore = Y
    5 6 | 5 6 7 8 | 7 6,  max = 8, ignore = N
    6 5 | 6 7 8 7 | 6 5,  max = 8, ignore = N
    5 6 | 7 8 7 6 | 5 4,  max = 8, ignore = N
    6 7 | 8 7 6 5 | 4 3,  max = 8, ignore = N
    7 8 | 7 6 5 4 | 3 2,  max = 8, ignore = Y
    8 7 | 6 5 4 3 | 2 1,  max = 8, ignore = Y
    7 6 | 5 4 3 2 | 1 2,  max = 7, ignore = Y
    
    推荐文章