Computação eficiente de uma combinação linear de colunas de dados.
eu tenhonc
colunas em um data.table enc
escalares em um vetor. Eu quero dar umacombinação linear das colunas, mas não sei de antemão quais colunas vou usar.Qual é a maneira mais eficiente de fazer isso?
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])
maneiras de fazer issoSuponha que eu queira usar as primeiras quatro colunas. Eu posso escrever manualmente:
DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)]
Eu posso pensar em duas formas automáticas (que funcionam sem saber que A-E deve ser usado):
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]
avaliação comparativaEspero que oas.matrix
para fazer a segunda opção lenta, e realmente não tem intuição para a velocidade deMap
-Reduce
combinações.
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
Eu chego em qualquer lugar de uma desaceleração de 5% a 40% por cento em relação à abordagem manual quando eu repito obenchmark
ligar.
As dimensões aqui -n
elength(mycols)
- estão perto do que estou trabalhando, mas estarei executando esses cálculos muitas vezes, alterando o vetor coeficiente,cf
.