2

假使,假设

x = c(1, 2, 3.5, 4, 6, 7.5, 8, 9, 10, 11.5, 12) 
y = c(2.5, 6.5) 
I = split(x, findInterval(x, y))
f = function(vec, x) {
        d = pmax(outer(x, vec, "-"), 0)
        colSums(d - d^2/2)
}

我想计算f(I[[i]], x)每个间隔的每个值中的值,然后找出每个间隔中哪个I[[i]]实际值具有最大值f(I[[i]], x )。有没有比这个 for 循环更有效的方法:

for (i in 1:length(I)) {
    max.values[[i]] = I[[i]][which.max(f(I[[i]], x))]
}

这是我想要得到的结果:

 > max.values
 [1]  2  6 10
4

3 回答 3

1

如果您只是对删除 for 循环感兴趣。您可以通过以下方式将其替换为 lapply(.):

max.values <- unlist( lapply( I, function(v) v[which.max(f(v, x))] ) );

这只会在长度(I)很大的情况下产生影响。为了获得更多的性能,看看你是否可以简化 f(.) 只是为了找到一个最大值。为了获得最佳优化,您应该考虑用 C、C++ 或 Fortran 重写性能关键部分。

当数据向量变大、存在冗长的循环或可用的数据结构不适合该任务时,R 可能会非常慢。就像轶事一样,我写了一个“for-loop”-less R 代码,在 Wall time 2 周后被杀死(输入数组:n ~ 1e6)。(R 代码在 n ~ 1e4 的输入上运行良好)。一个 C++ 等效代码需要 1 分钟。稍微优化的 C++ 代码需要 10 秒...

于 2012-05-01T03:20:57.747 回答
1

你可以做

mapply('[', I, lapply(lapply(I, f, x), which.max))
# 0  1  2 
# 2  6 10

以下是中间步骤:

lapply(I, f, x)
# $`0`
# [1] -190.875 -142.375
# 
# $`1`
# [1] -85.75 -70.75 -26.75
# 
# $`2`
# [1] -9.500 -6.125 -1.625  0.375  0.375  0.000

lapply(lapply(I, f, x), which.max)
# $`0`
# [1] 2
# 
# $`1`
# [1] 3
# 
# $`2`
# [1] 4
于 2012-05-01T03:06:56.957 回答
0

这更紧凑,但我不知道它是否更有效......

v <- sapply(lapply(I,f,x=x),which.max)
mapply(getElement,I,v)
于 2012-05-01T03:06:14.590 回答