Skuteczne obliczanie liniowej kombinacji kolumn data.table
mamnc
kolumny w tabeli danychnc
skalary w wektorze. Chcę wziąćkombinacja liniowa kolumn, ale nie wiem z wyprzedzeniem, które kolumny będę używać.Jaki jest najbardziej skuteczny sposób, aby to zrobić?
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])
sposoby, aby to zrobićZałóżmy, że chcę użyć pierwszych czterech kolumn. Mogę ręcznie napisać:
DT[,list(cf['A']*A+cf['B']*B+cf['C']*C+cf['D']*D)]
Mogę pomyśleć o dwóch automatycznych sposobach (ta praca bez wiedzy, że wszystkie A-E powinny być użyte):
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]
benchmarkingSpodziewam sięas.matrix
aby spowolnić drugą opcję i naprawdę nie mieć intuicji co do szybkościMap
-Reduce
kombinacje.
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
Powtarzam to od 5% do 40% spowolnienia w stosunku do ręcznego podejściabenchmark
połączenie.
Wymiary tutaj -n
ilength(mycols)
- są bliskie temu, z czym pracuję, ale będę wykonywać te obliczenia wiele razy, zmieniając wektor współczynników,cf
.