8

nc在 data.table 中有列,nc在向量中有标量。我想对列进行线性组合,但我事先不知道我将使用哪些列。最有效的方法是什么?

设置

require(data.table)
set.seed(1)

n  <- 1e5
nc <- 5
cf <- setNames(rnorm(nc),LETTERS[1:nc])
DT <- setnames(data.table(replicate(nc,rnorm(n))),LETTERS[1:nc])

方法

假设我想使用前四列。我可以手动编写:

DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)]

我可以想到两种自动方式(在不知道应该全部使用 AE 的情况下工作):

mycols <- LETTERS[1:4] # the first four columns
DT[,list(as.matrix(.SD)%*%cf[mycols]),.SDcols=mycols]
DT[,list(Reduce(`+`,Map(`*`,cf[mycols],.SD))),.SDcols=mycols]

基准测试

我希望使第二个选项变慢,并且对-组合as.matrix的速度真的没有直觉。MapReduce

require(rbenchmark)
options(datatable.verbose=FALSE) # in case you have it turned on

benchmark(
    manual=DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)],
    coerce=DT[,list(as.matrix(.SD)%*%cf[mycols]),.SDcols=mycols],
    maprdc=DT[,list(Reduce(`+`,Map(`*`,cf[mycols],.SD))),.SDcols=mycols]
)[,1:6]

    test replications elapsed relative user.self sys.self
2 coerce          100    2.47    1.342      1.95     0.51
1 manual          100    1.84    1.000      1.53     0.31
3 maprdc          100    2.40    1.304      1.62     0.75

当我重复benchmark调用时,相对于手动方法,我的速度会降低 5% 到 40%。

我的应用程序

这里的尺寸 -nlength(mycols)- 接近我正在使用的尺寸,但我将多次运行这些计算,改变系数向量,cf

4

2 回答 2

7

对我来说,这比您的手动版本快 2 倍:

Reduce("+", lapply(names(DT), function(x) DT[[x]] * cf[x]))

benchmark(manual = DT[, list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)],
          reduce = Reduce('+', lapply(names(DT), function(x) DT[[x]] * cf[x])))
#    test replications elapsed relative user.self sys.self user.child sys.child
#1 manual          100    1.43    1.744      1.08     0.36         NA        NA
#2 reduce          100    0.82    1.000      0.58     0.24         NA        NA

并迭代只是mycols,替换names(DT)mycolsin lapply

于 2013-10-09T18:09:06.927 回答
1

将此选项添加到您的基准调用中:

ops = as.matrix(DT) %*% cf

在我的设备上,它比您尝试的矩阵乘法快 30%。

于 2013-10-09T17:57:05.003 回答