在R中寻找局部最大值/最小值

9

我有一堆数据(每个测量系列大约有10,000到50,000个值),我希望自动识别这些值分布密度估计中的局部最大值/最小值。实际上,我假设通常应该有两个峰值,由一个低谷隔开,我想找到这个低谷,以便将数据分成两部分进行进一步处理。如果可能的话,我也想知道峰值的位置。

由于密度估计可能包含非常小的局部变化,我希望能够调整“灵敏度”。到目前为止,我能找到的最好的解决方案是@Tommy的解决方案:https://dev59.com/-mw15IYBdhLWcg3wFHzf#6836924 这里是一个例子:

library(ggplot2)

d <- density(faithful$eruptions, bw = "sj")
loc.max <- d$x[localMaxima(d$y)]

ggplot(faithful, aes(eruptions)) + geom_density(adjust=1/2) +
  geom_vline(x=loc.max, col="red") +
  xlab("Measured values")

在可信赖的数据集中识别最大值

现在,我的数据噪声很大:

d <- density(my.df$Values, bw = "sj")
loc.max <- d$x[localMaxima(d$y)]

ggplot(my.df, aes(Values)) + geom_density(adjust=1/2) +
  geom_vline(x=loc.max, col="red") +
  xlab("Measured values")

首次尝试在我的数据集中识别极值

尝试调整参数(注意尾部出现了两个“不需要”的峰值):

d <- density(my.df$Values, bw="nrd", adjust=1.2)
loc.max <- d$x[localMaxima(d$y)]

ggplot(my.df, aes(Values)) + geom_density(adjust=1/2) +
  geom_vline(x=loc.max, col="red") +
  xlab("Measured values")

在我的数据集中检测峰值的第二次尝试

因此,问题是:

1)如何在这样一个嘈杂的数据集中自动识别真实的峰值? 2)如何可靠地找到分隔这些峰值的谷底?


你如何定义“真正的峰值”? - Sven Hohenstein
@SvenHohenstein 这是一个好问题。我在数学上难以理解这个概念。应该有一个特定的窗口,使得峰值在其中是最大的。此外,最小峰值大小的截止值(可能与中位数有关)可能会有所帮助。如果我知道我的数据是双峰的,那么两个最高峰应该在一个相当大的窗口内得出(我承认,这又是模糊的)。如果我不知道峰值的数量,也许一个分离峰值的最大值和一个峰值的最小值的截止值会有所帮助? - AnjaM
1
光谱数据(色谱或光度计)的分析经常会遇到这个问题,因此您可以尝试在峰值识别的搜索中包含“spectr*”。@cbeleites既是SO参与者,也涉及该领域的活跃R软件包开发。 - IRTFM
@DWin 感谢您的建议!通过这种方式,我找到了一个叫做"PROcess"的Bioconductor包,用于光谱处理,似乎可以得到可接受的结果。 - AnjaM
2
你应该发布一个简单的已解决示例。 - IRTFM
1个回答

1

我最喜欢的是pastecs::turnpoints。但你说得对,你需要进行一些主观过滤来区分尖峰噪声和真正的峰值。一种方法是要求原始数据或样条数据在连续N个值中保持在某个阈值以上。


感谢您的建议。pastecs::turnpoints似乎没有提供定义跨度/窗口的可能性,因此我再次面临与上述方法相同的问题。我不确定如何实现您的建议来定义这样的阈值。另外,据我所知,它不能区分峰值和低谷,对吗? - AnjaM
哦,抱歉,我刚刚注意到你可以使用extract()方法区分峰值和低谷。我一定会更加仔细地研究这个函数的。但我仍然想知道过滤值的最佳方法是什么。 - AnjaM

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接