大家好,
我正在努力创建一列,该列将使用一个随机值生成值函数来填充值,该函数将另一列的值作为参数。
有点上下文-我在列中有一个提前期的数据表:
library(data.table)
dt <- data.table(Item = rep(123456,each = 1000), LT = rnorm(1000,mean = 10, sd = 3))
和一个功能
rand_ddlt_norm <- function(Lt,mean,sd){
sign(Lt) * ( sum( rnorm( floor(abs(Lt)), mean, sd) ) +
rnorm(1, mean, sd) * ( abs(Lt)%%1) )
}
以上功能旨在计算提前期中每一行的需求。
不幸的是,我不能这样做:
dt[,ddlt := rand_ddlt_norm(LT, mean = 100, sd = 30)]
因为所有行都将填充相同的数字。
我显然可以将其放入一个循环中,但是对于10,000次迭代,20,000多种产品和众多分布类型而言,计算时间变得可笑了。
我很欢迎任何有关如何在不运行循环的情况下优化此代码的建议。
答案 0 :(得分:3)
使用Vectorize()
对函数进行向量化。
# data
library(data.table)
set.seed(1)
dt <- data.table::data.table(Item = rep(123456,each = 1000), LT = rnorm(1000,mean = 10, sd = 3))
# def function
rand_ddlt_norm <- function(Lt,est11,est12){
sign(Lt) * ( sum( rnorm( floor(abs(Lt)), est11, est12) ) +
rnorm(1, est11, est12) * ( abs(Lt)%%1) )
}
rand_ddlt_norm <- Vectorize(rand_ddlt_norm) # vectorize it
dt[,ddlt := rand_ddlt_norm(LT, 100,30)]
结果:
> head(dt)
Item LT ddlt
1: 123456 8.120639 845.6967
2: 123456 10.550930 1112.5837
3: 123456 7.493114 733.3808
4: 123456 14.785842 1516.8916
5: 123456 10.988523 1101.0449
6: 123456 7.538595 898.3760
答案 1 :(得分:3)
我建议您直接向量化功能:
rand_ddlt_norm_vec <- function(Lt,mean,sd){
sign(Lt) * ( rowSums( t(sapply(1:length(Lt),function(x){rnorm(floor(abs(Lt)),mean,sd)}))) +
rnorm(length(Lt), mean, sd) * ( abs(Lt)%%1) )
}
现在Lt是向量。在这里
t(sapply(1:length(Lt),function(x){rnorm(floor(abs(Lt)),mean,sd)}))
创建一个矩阵,该矩阵的行数与Lt相同,列数与floor(abs(Lt))
相同。然后,您使用Rowsum
来获取向量。
与JdeMello的解决方案进行比较:
rand_ddlt_norm_vec2 <- Vectorize(rand_ddlt_norm)
library(microbenchmark)
library(data.table)
dt <- data.table(Item = rep(123456,each = 10000), LT = rnorm(10000,mean = 10, sd = 3))
microbenchmark(
denis = function(){dt[,ddlt := rand_ddlt_norm_vec(LT, mean = 100, sd = 30)]},
jdeMello = function(){dt[,ddlt := rand_ddlt_norm_vec2(LT, mean = 100, sd = 30)]}
)
Unit: nanoseconds
expr min lq mean median uq max neval cld
denis 0 0 0.24 0 0 1 100 a
jdeMello 0 0 25.88 0 0 2566 100 a
此解决方案比JdeMello解决方案快100倍。