我有一个问题,我需要对向量进行一些操作,对于向量内的每个值,我需要根据给定的上升范围L
,为该值计算“上升”值。
例如,在10
位置的值3rd
,加速功能将返回[2.5, 5]
,该值应该是该值{{1}的加速值},它们位于10
的位置。
我想要的结果是一个单一向量,它也是一个向量,但具有所有加速效果。
我已经使用了一些方法来成功获得正确的结果。
因为我需要做很多这样的操作,所以我想知道是否有更快的方法来实现它。 (profvis显示此操作是我脚本的瓶颈)
这是一个简单的例子
1st, 2nd
x = c(0, 0, 5, 10, 10, 20, 10)
L = 2
r = matrix(0, L, length(x))
for(i in 1: L)
{
r[i, ] = map(x, ramp, L) %>%
map_dbl(i) %>%
lead(L-i+1, default = 0)
}
结果矩阵r
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1.250000 2.500000 2.500000 5.000000 2.500000 0.000000 0
[2,] 0.000000 2.500000 5.000000 5.000000 10.000000 5.000000 0
的第一行是移到正确位置后的第一个加速值,第二行是第二个加速值。
我想要的最终返回向量是
r
任何建议都值得欢迎,谢谢。
为清楚起见,这是我使用的colSums(r)
函数,半斜坡只是为了易于理解的示例。
ramp()
这是结果
ramp <- function(Value, Len, R = 0.5)
{
out <- c(1:(Len+1))
if(R != 0) { out <- exp(R*c(1:(Len+1)))*Value/exp(R*(Len+1)) }
else { out <- c(rep(0, Len), Value) }
return(out)
}
x = c(0, 0, 5, 10, 10, 20, 10)
L = 2
r = matrix(0, L, length(x))
for(i in 1: L)
{
r[i, ] = map(x, ramp, L) %>% map_dbl(i) %>% lead(L-i+1, default = 0)
}
r
[,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 1.839397 3.678794 3.678794 7.357589 3.678794 0.000000 0
[2,] 0.000000 3.032653 6.065307 6.065307 12.130613 6.065307 0
答案 0 :(得分:0)
到目前为止,我想发表一些尝试来提高流程效率。
我要做的第一件事是优化我的ramp.all()
步骤,这是我的示例脚本的第二部分。
ramp.all.old.1 <- function(x, L)
{
r = rep(0, length(x))
for(i in 1: L)
{
r = rbind(r, map(x, ramp, L) %>% map_dbl(i) %>% lead(L-i+1, default = 0))
}
return(colSums(r))
}
当我阅读其他文章时,我注意到rbind()
可能不是达到我目的的最佳选择。因此,第一个尝试是预先分配结果矩阵r
,所以我得到了第二个版本。
ramp.all.old.2 <- function(x, L)
{
r = matrix(0, L, length(x))
for(i in 1: L)
{
r[i, ] = map(x, ramp, L) %>% map_dbl(i) %>% lead(L-i+1, default = 0)
}
return(colSums(r))
}
然后,当我仔细查看循环中的代码时,我注意到map()
实际上是多余的,它只需要在循环之前计算一次即可。因此我将map()移出,并用lapply()
代替。
ramp.all.old.3 <- function(x, L)
{
r = matrix(0, L, length(x))
tmp = lapply(x, ramp, L)
for(i in 1: L)
{
r[i, ] = tmp %>% map_dbl(i) %>% lead(L-i+1, default = 0)
}
return(colSums(r))
}
类似地,map_dbl()
似乎没有经过优化,还有更好的方法。因此,我推出了版本4。
ramp.all.old.4 <- function(x, L)
{
r = matrix(0, L, length(x))
tmp = as.data.frame(data.table::transpose(lapply(x, ramp, L)), col.names = letters[1:(L+1)])
for(i in 1: L)
{
r[i, ] = lead(tmp[, i], L-i+1, default = 0)
}
return(colSums(r))
}
正如@Gregor所建议的那样,加速ramp()
函数在这里也很重要。我想出了一种更改ramp()
函数的方法,该函数现在可以利用 out-product 操作将 vector 作为输入。我想出了ramp.new()
函数
ramp.new <- function(Value, Len, R = 0.5)
{
out = Value %*% t(exp(R*c(1:(Len+1)))/exp(R*(Len+1)))
return(out)
}
新的ramp.all()
函数是
ramp.all <- function(x, L)
{
r = matrix(0, L, length(x))
tmp = ramp.new(x, L)
for(i in 1: L)
{
r[i, ] = lead(tmp[, i], L-i+1, default = 0)
}
return(colSums(r))
}
这是性能测试结果。
x
[1] 0 0 5 10 10 20 10
microbenchmark(ramp.all.old.1(x, 2)->res.1, ramp.all.old.2(x, 2)->res.2, ramp.all.old.3(x, 2)->res.3, ramp.all.old.4(x, 2)->res.4,ramp.all(x, 2)->res.5)
Unit: microseconds
expr min lq mean median uq max neval cld
res.1 <- ramp.all.old.1(x, 2) 529.461 565.0145 603.9836 589.810 618.7990 816.800 100 d
res.2 <- ramp.all.old.2(x, 2) 526.909 565.1965 619.6961 590.357 623.7215 1684.649 100 d
res.3 <- ramp.all.old.3(x, 2) 441.582 472.0305 512.1629 500.655 525.0860 859.463 100 c
res.4 <- ramp.all.old.4(x, 2) 299.736 331.4610 375.3600 350.422 385.7930 1232.857 100 b
res.5 <- ramp.all(x, 2) 34.277 47.7680 56.4947 50.504 56.3385 137.470 100 a
identical(res.1, res.2, res.3, res.4, res.5)
[1] TRUE
到目前为止,我还很高兴。检查profvis
,看来我下一步应该专注于lead()
函数。
欢迎其他任何建议,谢谢@ akrun,@ Gregor。