1

130 万行のデータ フレームがあり、これを地域的および一時的な要約に集約する必要があります。Plyrの構文は簡単ですが、実際には遅すぎます (1ddply時間実行して、25% 未満しか完了していません)。ddply構文を変換data.tableして、その自慢の速度を活用するための助けを探しています。

私のデータは次のタイプです

library(plyr)
library(lubridate)

dat <- expand.grid(area = letters[1:2],
                    day = as.Date("2012-10-01") + c(0:10) * days(1),
                   type = paste("t", 1:2, sep=""))
dat$val <- runif(44)

行数 (おもちゃのデータを考えると、ここでは等しくなります) と、valさまざまな期間の変数の合計が必要です。

このddply呼び出しは、私が探しているものを教えてくれます

count.and.sum <- function(i){
  if(i$day >= as.Date("2012-10-02")){
     k <- data.frame(c_1d = nrow(dat[dat$type == i$type &
                                     dat$area == i$area &
                                     dat$day %in% i$day - days(1),]),
                     c_2d = nrow(dat[dat$type == i$type &
                                     dat$area == i$area &
                                     dat$day %in% (i$day - c(1:2) * days(1)),]),
                     s_1d = sum(dat$val[dat$type == i$type &
                                        dat$area == i$area &
                                        dat$day %in% i$day - days(1)]),
                     s_2d = sum(dat$val[dat$type == i$type &
                                        dat$area == i$area &
                                        dat$day %in% (i$day - c(1:2) * days(1))]))
  return(k) 
  }
 }

ddply(dat, .(area, day, type), count.and.sum)[1:10,]

data.tableあなたが提供できる構文を本当に感謝します。

4

1 に答える 1

2

まず、あなたの関数はひどく非効率的であり、plyr に渡される関数がどのように見えるべきかについての理解の欠如を露呈しています。ddply() の場合、汎用データ フレームを入力として受け取り、データ フレームを出力する必要があります。このコンテキストでの「ジェネリック」とは、グループ化変数のレベルの組み合わせによって定義される「分割」のいずれかとして生成されるデータ フレームを意味します。関数は次のようになります。

count.and.sum <- function(d) data.frame(n = length(d$val), valsum = sum(d$val))

グループ化変数の組み合わせは、ddply() 呼び出しで処理されます。

次に、ddply()各観測が地域、日、およびタイプの固有の組み合わせに関連付けられているため、呼び出しによって 1 行のデータ フレームが作成されます。このおもちゃの例のより現実的なアプリケーションはddply()、日ごとに要約することです。

summarise「適用」関数として使用する直接的な方法:

ddply(dat, .(day), summarise, nrow = length(val), valsum = sum(val))

使用count.and.sum:

ddply(dat, .(day), count.and.sum)

これは、お使いのバージョンの よりもはるかに高速である可能性が非常に高くなりますcount.and.sum

同等の data.table バージョン (必ずしも最も効率的であるとは限りません) については、次を試してください。

library(data.table)
DT <- data.table(dat, key = c('area', 'day', 'type'))

DT[, list(n = length(val), valsum = sum(val)), by = 'day']

以下は、100K の観測値を使用したもう少し精巧なおもちゃの例です。

set.seed(5490)
dat2 <- data.frame(area = sample(letters[1:2], 1e5, replace = TRUE),
                   day = sample(as.Date("2012-10-01") + c(0:10) * days(1),
                                  1e5, replace = TRUE),
                   type = sample(paste0("t", 1:2), 1e5, replace = TRUE),
                   val = runif(1e5))

system.time(u <- ddply(dat2, .(area, day, type), summarise, 
                      n = length(val), valsum = sum(val)))

DT2 <- data.table(dat2, key = c('area', 'day', 'type'))
system.time(v <- DT2[, list(n = length(val), valsum = sum(val)), by = key(DT)])

identical(u, as.data.frame(v))

私のシステムでは、data.tableバージョンはバージョンよりも約 4.5 倍高速ですplyr(plyr で 0.09 秒、data.table で 0.02 秒)。

于 2013-05-11T08:58:47.390 に答える