我正在寻找一种功能,可以在我提供的起点上对矢量进行简单的爬山。更正式地说:给定y <- c(1,2,3,1,1)
之类的向量,我想要一个函数hill(y, x0)
,使得hill(y, 1) == 3
(从左边爬到顶部)和hill(y, 5) == 5
(它左右移动) ,但发现它在高原上,只返回起始值)。我很难相信这不存在,但到目前为止还没有找到它。有人带头吗?
答案 0 :(得分:2)
这是一个来自https://gist.github.com/3000200的递归解决方案。为简洁而省略了测试。
climb <- function(y, x0) {
x <- index(y)
n <- length(y)
if (n == 0) { return(NA) }
if (x0 < min(x) | x0 > max(x)) {
warning(sprintf("x0 of %f lies outside data range [%f, %f]", x0, min(x), max(x)))
}
# TODO: beautify this.
w <- which.min(abs(as.numeric(x - x0)))
i <- x[w]
ii <- index(x)[w] # 1-based index
l <- x[ii-1]
r <- x[ii+1]
yl <- if (ii == 1) { -Inf } else { as.numeric(y[l]) }
yr <- if (ii == n) { -Inf } else { as.numeric(y[r]) }
yi <- as.numeric(y[i])
# At a maximum?
if (yl <= yi && yr <= yi) {
return(i)
}
# Nope; go in the direction of greatest increase, breaking ties to the right.
if (yl > yr) {
return(climb(y, l))
} else {
return(climb(y, r))
}
}
答案 1 :(得分:1)
我认为没有一个功能可以做到这一点,任务太简单和专业。更一般的情况是在向量或时间序列中找到局部最大值:
给定x
,然后[可以写成一行]
lmax <- function(x) {
x <- c(x[1], x, x[length(x)])
d <- diff(sign(diff(x)))
which(d < 0)
}
将返回x
中所有(本地)最大值的索引。从某个索引i
开始,现在很容易找到其附近的最大值。例如:
x <- c(10,10, 9, 4,10,10,10, 1, 2, 5, 4, 4)
lmax(x) # 2 5 7 10
如果您从i = 4
开始,则必须查看 - 例如,应用findInterval
- 哪一个更高,x[2]
或x[5]
。如果你不想涉及平坦的山谷(或平原),例如i=6
,一些if
陈述将进入。因此行人的方法似乎更合适:
hill <- function(x, i) {
stopifnot(is.numeric(x), 1 <= i, i <= length(x))
i1 <- i2 <- i
while (i1 < length(x))
if (x[i1 + 1] > x[i1]) i1 <- i1 + 1 else break
while (i2 > 1)
if (x[i2 - 1] > x[i2]) i2 <- i2 - 1 else break
# return
if (x[i1] >= x[i2]) i1 else i2
}
当然,我希望看到一个更加矢量化的解决方案。
答案 2 :(得分:0)
我怀疑您正在寻找cumsum
或cummax
,但您的数学有问题:
?cummax # on same help page as cumsum
> y <- c(1,2,3,1,1)
> cummax(y)
[1] 1 2 3 3 3
> cumsum(y)
[1] 1 3 6 7 8
但后来我在RSeek.org上搜索“爬山”并发现你想要别的东西。包中有这样的函数:例如'FSelector'中的hill.climbing.search
。