在R中找到局部最大值和最小值

时间:2015-12-10 15:17:47

标签: r minima

我试图创建一个函数来查找" maxima"和" minima"。我有以下数据:

  y
  157
  144
   80
  106
  124
   46
  207
  188
  190
  208
  143
  170
  162
  178
  155
  163
  162
  149
  135
  160
  149
  147
  133
  146
  126
  120
  151
   74
  122
  145
  160
  155
  173
  126
  172
   93

我试过这个功能来找到" maxima"

localMaxima <- function(x) {
  # Use -Inf instead if x is numeric (non-integer)
  y <- diff(c(-.Machine$integer.max, x)) > 0L
  rle(y)$lengths
  y <- cumsum(rle(y)$lengths)
  y <- y[seq.int(1L, length(y), 2L)]
  if (x[[1]] == x[[2]]) {
    y <- y[-1]
  }
  y
}

maks <- localMaxima(x)

找到&#34; minima&#34;

的功能
localMinima <- function(x) {
      # Use -Inf instead if x is numeric (non-integer)
      y <- diff(c(.Machine$integer.max, x)) > 0L
      rle(y)$lengths
      y <- cumsum(rle(y)$lengths)
      y <- y[seq.int(1L, length(y), 2L)]
      if (x[[1]] == x[[2]]) {
        y <- y[-1]
      }
      y
    }

    mins <- localMinima(x)

结果不是100%正确

maks = 1  5  7 10 12 14 16 20 24 27 31 33 35
mins = 3  6  8 11 13 15 19 23 26 28 32 34 36

结果应

maks = 5  7 10 12 14 16 20 24 27 31 33 35
mins = 3  6  8 11 13 15 19 23 26 28 32 34

Finding local maxima and minima in R接近,但并不合适。

我该如何解决这个问题?

非常感谢你

2 个答案:

答案 0 :(得分:4)

您可以定义两个函数,如下所示,它们生成您需要的向量:

library(data.table)
#shift lags or leads a vector by a certain amount defined as the second argument
#the default is to lag a vector.
#The rationale behind the below code is that each local minimum's adjucent
#values will be greater than itself. The opposite is true for a local 
#maximum. I think this is what you are trying to achieve and one way to do 
#it is the following code
maximums <- function(x) which(x - shift(x, 1) > 0  & x - shift(x, 1, type='lead') > 0)
minimums <- function(x) which(x - shift(x, 1) < 0  & x - shift(x, 1, type='lead') < 0)

输出:

> maximums(y)
 [1]  5  7 10 12 14 16 20 24 27 31 33 35
> minimums(y)
 [1]  3  6  8 11 13 15 19 23 26 28 32 34

答案 1 :(得分:2)

这是我前一段时间写的一个功能(它比你需要的更通用)。它在序列数据x中找到峰值,其中我将峰值定义为局部最大值,其中m点的任何一侧都具有低于它的值(因此更大m会导致更严格的标准寻找高峰):

 find_peaks <- function (x, m = 3){
     shape <- diff(sign(diff(x, na.pad = FALSE)))
     pks <- sapply(which(shape < 0), FUN = function(i){
        z <- i - m + 1
        z <- ifelse(z > 0, z, 1)
        w <- i + m + 1
        w <- ifelse(w < length(x), w, length(x))
        if(all(x[c(z : i, (i + 2) : w)] <= x[i + 1])) return(i + 1) else return(numeric(0))
    })
     pks <- unlist(pks)
     pks
}

因此,对于您的案例m = 1

 find_peaks(x, m = 1)
 #[1]  5  7 10 12 14 16 20 24 27 31 33 35

和最小值:

 find_peaks(-x, m = 1)
 #[1]  3  6  8 11 13 15 19 23 26 28 32 34