一列中基于另一列值的随机数

时间:2019-01-11 13:01:14

标签: r random data.table

大家好,

我正在努力创建一列,该列将使用一个随机值生成值函数来填充值,该函数将另一列的值作为参数。

有点上下文-我在列中有一个提前期的数据表:

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多种产品和众多分布类型而言,计算时间变得可笑了。

我很欢迎任何有关如何在不运行循环的情况下优化此代码的建议。

2 个答案:

答案 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倍。