Cálculo eficiente de una combinación lineal de columnas data.table.

yo tengonc columnas en una tabla de datos, ync Scalars en un vector. Quiero tomar uncombinación lineal de las columnas, pero no sé de antemano qué columnas usaré.¿Cuál es la forma más eficiente de hacer esto?

preparar
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])
maneras de hacerlo

Supongamos que quiero usar las primeras cuatro columnas. Puedo escribir manualmente:

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

Puedo pensar en dos formas automáticas (que funcionan sin saber que A-E debe usarse todas):

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]
evaluación comparativa

Espero elas.matrix para hacer la segunda opción lenta, y realmente no tienen intuición para la velocidad deMap-Reduce combinaciones

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

Obtengo de un 5% a un 40% de desaceleración en relación con el enfoque manual cuando repito elbenchmark llamada.

mi aplicación

Las dimensiones aquí -n ylength(mycols) - están cerca de lo que estoy trabajando, pero ejecutaré estos cálculos muchas veces, alterando el vector de coeficiente,cf.

Respuestas a la pregunta(2)

Su respuesta a la pregunta