8

ncdata.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])

それを行う方法

最初の 4 つの列を使用するとします。私は手動で書くことができます:

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

2 つの自動的な方法を考えることができます (すべて 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]

ベンチマーク

私は 2 番目のオプションを遅くすることを期待しており、 -の組み合わせ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

通話を繰り返すと、手動のアプローチに比べて 5% から 40% の速度低下が見られbenchmarkます。

私のアプリケーション

ここの次元 --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

just を反復処理するには、inmycolsに置き換えます。names(DT)mycolslapply

于 2013-10-09T18:09:06.927 に答える
1

このオプションをベンチマーク コールに追加します。

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

私のデバイスでは、試した行列乗算よりも 30% 高速でした。

于 2013-10-09T17:57:05.003 に答える