3

私はdata.tableこれに似たオブジェクトを持っています

library(data.table)

c <- data.table(CO = c(10000,10000,10000,20000,20000,20000,20000),
                SH = c(1427,1333,1333,1000,1000,300,350),
                PRC = c(6.5,6.125,6.2,0.75,0.5,3,3.5),
                DAT = c(0.5,-0.5,0,-0.1,NA_real_,0.2,0.5),
                MM = c("A","A","A","A","A","B","B"))

ネストされたグループ化を使用して計算を実行しようとしています。引数として式を渡します。これが私が持っているものの簡略版です:

setkey(c,MM)

mycalc <- quote({nobscc <- length(DAT[complete.cases(DAT)]); 
                 list(MKTCAP = tail(SH,n=1)*tail(PRC,n=1),
                      SQSUM = ifelse(nobscc>=2, sum(DAT^2,na.rm=TRUE), NA_real_),
                      COVCOMP = ifelse(nobscc >= 2, head(DAT,n=1), NA_real_),
                      NOBS = nobscc)}) 


myresults <- c[,.SD[,{setkey=CO; eval(mycalc)},by=CO],by=MM]

を生成します

     MM    CO MKTCAP SQSUM COVCOMP NOBS
[1,]  A 10000 8264.6  0.50     0.5    3
[2,]  A 20000  500.0    NA      NA    1
[3,]  B 20000 1225.0  0.29     0.2    2

上記の例では、構成を使用するリストの2つの要素がありifelse(実際のコードには3つあります)、すべて同じテストを実行します。観測数が2より大きい場合、特定の計算(リストの各要素、およびそれぞれを関数として記述できます)が実行されます。それ以外の場合は、これらの要素の値をNAにします。data.tableこれらの要素に共通するもう1つの点は、私の同じ列を使用していることDATです。

だから私の質問は:私が一度だけテストを行うことができる方法はありますかifelse、そしてそれがFALSEの場合NA、リストのそれぞれの要素に値を渡し、TRUEの場合、リストの要素ごとに異なる式を評価します?

注:私の目標は、system.time(システムと経過)を減らすことです。この変更で時間と計算が減らない場合は、7,200万回の観測があることを念頭に置いて、それは許容できる答えです。コードの他の部分を変更する提案も歓迎します。

編集:summaryRprof()の結果

$by.total
                          total.time total.pct self.time self.pct
"system.time"                  18.94     99.79      0.00     0.00
".Call"                        18.92     99.68      0.10     0.53
"["                            18.92     99.68      0.04     0.21
"[.data.table"                 18.92     99.68      0.02     0.11
"eval"                         18.80     99.05      0.24     1.26
"ifelse"                       18.30     96.42      0.46     2.42
"lm"                           17.70     93.26      0.58     3.06
"sapply"                        8.06     42.47      0.36     1.90
"model.frame"                   7.74     40.78      0.16     0.84
"model.frame.default"           7.58     39.94      0.98     5.16
"lapply"                        6.62     34.88      0.70     3.69
"FUN"                           4.24     22.34      1.10     5.80
"model.matrix"                  4.04     21.29      0.02     0.11
"model.matrix.default"          4.02     21.18      0.26     1.37
"match"                         3.66     19.28      0.86     4.53
".getXlevels"                   3.12     16.44      0.12     0.63
"na.omit"                       2.40     12.64      0.24     1.26
"%in%"                          2.30     12.12      0.34     1.79
"simplify2array"                2.24     11.80      0.12     0.63
"na.omit.data.frame"            2.16     11.38      0.14     0.74
"[.data.frame"                  2.12     11.17      1.18     6.22
"deparse"                       1.80      9.48      0.66     3.48
"unique"                        1.80      9.48      0.54     2.85
"[["                            1.52      8.01      0.12     0.63
"[[.data.frame"                 1.40      7.38      0.54     2.85
".deparseOpts"                  1.34      7.06      0.96     5.06
"paste"                         1.32      6.95      0.16     0.84
"lm.fit"                        1.20      6.32      0.64     3.37
"mode"                          1.14      6.01      0.14     0.74
"unlist"                        1.12      5.90      0.56     2.95
4

1 に答える 1

4

このようなデータサブセットを形成して操作する代わりに、次のようにします。

setkey(c,MM)
myresults <- c[, .SD[,{setkey=CO; eval(mycalc)},by=CO], by=MM]

あなたはこれをやってみることができます:

setkeyv(c, c("MM", "CO"))
myresults <- c[, eval(mycalc), by=key(c)]

これにより、.SDオブジェクトのネストされたサブセットがすべて回避されるため、コードが高速化されます。各オブジェクトには、独自の.SDオブジェクトの呼び出しが必要[.data.tableです。


元の質問では、ifelse評価に時間がかかるとは思えませんが、評価を避けたい場合は、評価を削除して、目的の値を次のmycalcよう:=に上書きすることができます。NA

mycalc <- quote(list(MKTCAP = tail(SH,n=1)*tail(PRC,n=1),
                      SQSUM = sum(DAT^2,na.rm=TRUE),
                      COVCOMP = head(DAT,n=1),
                      NOBS = length(DAT[complete.cases(DAT)]))) 
setkeyv(c, c("MM", "CO"))
myresults <- c[, eval(mycalc), by=key(c)]


myresults[NOBS<2, c("SQSUM", "COVCOMP"):=NA_real_]
## Or, alternatively
# myresults[NOBS<2, SQSUM:=NA_real_]
# myresults[NOBS<2, COVCOMP:=NA_real_]
于 2012-06-29T16:50:42.523 に答える