简体   繁体   English

将函数应用于data.table中的矢量化列值

[英]Apply function to vectorised column values in data.table

Please consider this 请考虑一下

library(data.table)
mydt <- 
  data.table(id = 1:100,
           p1 = sample(seq(0,1,length.out=1000),100))
mydt$p2 <- 1 - mydt$p1

I want to apply a function using as the argument a vector from columns p1 and p2 . 我想应用一个函数,使用p1p2列中的向量作为参数。

myFun <- function(x) {
  sample(c(1,2), 1, prob = x)
}

This works, 这样有效

mydt$outcome <- apply(mydt[,2:3], 1, myFun)

but I have a 25M rows, so I reach the memory limit. 但是我有2500万行,所以我达到了内存限制。

I tried this, but it doesn't work. 我试过了,但是没有用。

mydt[,mydt := mapply(myFun, p1, p2)]

prob argument in sample requires a vector. sample prob参数需要向量。 And to apply myFun to each row, you can use by=1:nrow(mydt) or by=1:mydt[,.N] 并将myFun应用于每一行,可以使用by=1:nrow(mydt)by=1:mydt[,.N]

mydt[, chosen := myFun(c(p1, p2)), by=1:nrow(mydt)]

Hat-tip to @Roland for his usage of rbinom . 向@Roland推荐使用rbinom His vectorized version for this Bernoulli trial is much faster. 他在伯努利试验中使用的矢量化版本要快得多。

> system.time(mydt[, chosen := myFun(c(p1, p2)), by=1:nrow(mydt)])
   user  system elapsed 
   4.82    0.00    4.86 
> system.time(mydt[, outcome2 := rbinom(.N, 1, p2) + 1])
   user  system elapsed 
   0.05    0.02    0.06 

data used in timings: 计时中使用的数据:

library(data.table)
set.seed(0L)
m <- 1e6
mydt <- data.table(id = 1:m, p1 = runif(m))[, p2 := 1 - p1]
myFun <- function(x) sample(c(1,2), 1, prob = x)

accuracy check: 准确性检查:

n <- 0L
while (n < 1e3) {
    set.seed(n)
    mydt[, chosen := myFun(c(p1, p2)), by=1:nrow(mydt)]

    set.seed(n)
    mydt[, outcome2 := rbinom(.N, 1, p2) + 1]

    if(!all.equal(mydt$chosen, mydt$outcome2)) stop("mismatch")
    n <- n + 1
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM