Php 如何找到潮汐数据的所有波峰和波谷?
我正在处理一些海洋潮汐数据,其结构如下:Php 如何找到潮汐数据的所有波峰和波谷?,php,multidimensional-array,inflection,Php,Multidimensional Array,Inflection,我正在处理一些海洋潮汐数据,其结构如下: $data = array('date' => array('time' => array('predicted','observed'))); 以下是我正在使用的真实数据示例: 这是我试图找到高/低值的尝试: 我的代码当前存在的问题: 当读数波动时(如样本数据中11/14/2010=>11:30:00至11/14/2010=>11:54:00范围所示),会在方向逻辑中产生“摆动”。这会产生错误的峰谷。我如何避免/纠正这种情况 注意:我
$data = array('date' => array('time' => array('predicted','observed')));
以下是我正在使用的真实数据示例:
这是我试图找到高/低值的尝试:
我的代码当前存在的问题:
- 当读数波动时(如样本数据中
至11/14/2010=>11:30:00
范围所示),会在方向逻辑中产生“摆动”。这会产生错误的峰谷。我如何避免/纠正这种情况11/14/2010=>11:54:00
注意:我的方法非常“特别”。。我想我不需要任何很棒的数学知识,因为我不想找到任何平均值、近似值或未来的估计值。我非常欣赏一个更好方法的代码示例,即使这意味着扔掉我迄今为止编写的代码。我还没有详细阅读,但您的方法似乎非常特别。更正确的方法可能是将其与函数相匹配
f(A,B,w,p;t)=Asin(wt+p)+B
使用一种方法,例如(不幸的是,必须使用迭代方法来解决)。看看你的样本数据,它似乎是一个很好的适合。当计算w和p时,只需取函数的时间导数并求零,就可以很容易地确定峰值和谷值:
t = (pi(1+2n)-2p)/w
但我想,如果你的代码真的做到了你想要的,那么把事情复杂化是没有用的。不要再怀疑自己了。:) 峰值/谷值检测的准确度如何?如果你只需要找到峰谷发生的确切记录,检查拐点还不够吗 e、 g.考虑位置“i”处的记录,如果记录[i-1]和记录[i+1]都比记录[i]高,则有一个谷。如果记录[i-1]和记录[i+1]都比记录[i]低,就有一个峰值。只要你的采样率比潮汐变化快(查找),这个过程就会得到你的数据的波峰/波谷
如果你需要从这张图中生成一张图表,并尝试为波峰/波谷推断出更准确的时间点,那么你就需要做更多的工作。我不得不对嘈杂的生理数据执行类似的任务。在我看来,你有一个信号调节问题。这是一个对我有用的过程
一种方法可能是定义一个绝对或相对偏差,超过该偏差,您将进一步的峰/谷分类为新的峰/谷,而不是现有峰/谷周围的波动
目前,<代码> $方向>代码>确定你是否找到了一个峰值或波谷,因此,在符号的导数变化之后,不要转换到另一个状态(找到槽或峰值),只有当偏离当前的峰值/波谷为“大”时,才可以考虑改变状态。够了。
我想你是在寻找局部极小值和极大值吧?这很容易做到:<?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
半径范围内的最小值/最大值,这可能会给您的数据集带来误报明智地选择半径。
你必须把它编入你的脚本中,但这一点也不难
祝你好运 如果你不应该在大约12小时内看到两个最大值或两个最小值,一个简单的解决方案是使用3-5小时左右的滑动窗口,找到最大值和最小值。如果它在第一个或最后30分钟内是最大值,则忽略它 例如,给出以下数据:
1 2 3 4 5 6 5 6 7 8 7 6 5 4 3 2 1 2
还有一个大小为8的窗口,第一个和最后两个窗口被忽略,只看一眼就会看到:
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
一个问题是,我认为观察值是观察值,可能包含小误差。这至少需要考虑到。例如:
- 仅当至少下两个条目也位于同一方向时才更改方向
- 不要让数据差异太小而做出决策。扔掉无关紧要的数字。如果你说
并将条件更改为$error=0.10,可能会好得多
等等如果$previous-$error>$current