Эффективное вычисление линейной комбинации столбцов data.table

у меня есть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)]

Я могу думать о двух автоматических способах (которые работают, не зная, что все A-E должны использоваться):

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 сделать второй вариант медленным, и на самом деле нет никакой интуиции для скоростиMap-Reduce комбинации.

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

Я получаю от 5% до 40% процента замедления по сравнению с ручным подходом, когда я повторяюbenchmark вызов.

мое приложение

Размеры здесь -n а такжеlength(mycols) - близки к тому, с чем я работаю, но я буду выполнять эти вычисления много раз, изменяя вектор коэффициента,cf.

Ответы на вопрос(2)

Ваш ответ на вопрос