2015-12-10 77 views
1

我正在尝试创建一个函数来查找“最大值”和“最小值”。我有以下数据:在R中寻找当地最大值和最小值

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 

我曾尝试这个功能找到 “千里马”

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) 

而且funtion找到 “极小”

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 %right

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 

r应该是

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

你如何定义一个LOCA最大/最小?两个相邻值更高/更低的位置? – Heroka

回答

3

你可以定义像下面这产生你所需要的载体有两个功能:

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

这是一个功能我写了一而后面(而且比你需要的更一般)。它发现峰在顺序数据x,其中i限定的峰作为局部最大值与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 
+0

@ stas_g ..我正在使用您的解决方案。我只是想澄清一下,函数中的'm = 3'。这是否意味着'默认'的长度?所以如果我只输入find_peaks(x) - 这将有一个默认的m = 3? – Lyndz