在R中找到每个区间函数最大值的最快方法

4

我有一个向量 v 和一个区间向量 w。我想在每个区间内找到函数 f(x) 的最大值。有没有比下面的代码更快的方法来实现这个目标?

v = c(3.5, 2.5, 4, 6.5, 10, 2.3, 1.8, 4.7, 12, 11.5)
w = c(0, 5, 15, 20)
f = function(x){x^2}
> max = unlist(list(sapply(split(v, cut(v, w),drop = TRUE),
               function(v) v[which.max(f(v))])), use.names = FALSE)
> max
[1]  4.7 12.0

你是否担心 w 定义了三个集合(其中一个为空),但是你的输出是长度为 2 的向量?相反,你是否考虑将长度为 3 的列表作为你的输出? - flodel
不,我只需要结果,不含任何间隔,使用numeric()函数。 - rose
看起来对我已经进行了优化,但你可以删除 unlist(list( 并将 sapply 替换为 vapply。需要注意的一点是,每个区间都会调用一次 f。如果区间变得更多(并且更小),这可能会成为瓶颈,具体取决于 f 的编码方式。 - Ferdinand.kraft
我将它们删除了,但是出现了以下错误:> max = vapply(split(v, cut(v, w)),function(v) v[which.max(f(v))]) vapply(split(v, cut(v, w)), function(v) v[which.max(f(v))])中的参数“FUN.VALUE”缺失且没有默认值。 - rose
@rose,你可以添加参数FUN.VALUE=numeric(1)来指示你的函数返回长度为1的数字向量。将其放在函数后面即可。 - Ferdinand.kraft
1个回答

4

那么findIntervaltapply呢?findInterval类似于cut,但不需要转换为因子的开销。

tapply(v,findInterval(v,w),function(x)x[which.max(f(x))])
#   1    2 
#  4.7 12.0

如果你想得到最大值

tapply(f(v),findInterval(v,w),max)
#    1      2 
# 22.09 144.00

你可以利用函数在所有正值上单调递增的事实来进行操作。
f(tapply(v,findInterval(v,w),max))

请注意,您需要指定边界处发生的情况(请阅读帮助文件)。
library(microbenchmark)
     microbenchmark(
        mnel = tapply(v,findInterval(v,w),max),
        flodel = unname(vapply(split(f(v), cut(v, w), drop = TRUE), max, numeric(1L))),
        flodel2 = unname(vapply(split(seq_along(v), findInterval(v, w)), function(i, v, fv)v[i][which.max(fv[i])], numeric(1L), v, f(v))))
#  Unit: microseconds
#   expr     min       lq   median       uq     max neval
#   mnel 260.945 262.9155 264.2265 276.0645 458.670   100
# flodel 331.218 334.3585 336.0580 351.1985 694.715   100
#flodel2 124.998 127.3230 128.5170 137.0505 354.545   100

如何从结果中删除标题? - rose
我的期望结果是在每个区间内具有最大f(x)值的v值,而不是f(x)的值。> max [1] 4.7 12.0 - rose
1
@rose - 你对自己想要的东西感到困惑。对于所有正值,你的函数都是单调递增的,因此在一个区间内v的最大值将给出f(v)的最大值。我已经为你提供了代码来完成这两个任务。使用你需要的那个即可。 - mnel
4
请尝试使用以下代码:unname(vapply(split(seq_along(v), findInterval(v, w)), function(i, v, fv)v[i][which.max(fv[i])], numeric(1L), v, f(v))) - flodel

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