2013-05-22 34 views
7

我試圖達到與data.table一樣的效果。因此,正如一個很簡單的例子:等同於data.table中的dlply

library(plyr) 
library(data.table) 
dt <- data.table(p = c("A", "B"), q = 1:2) 

dlply(dt, "p", identity) 
$A 
    p q 
1 A 1 

$B 
    p q 
1 B 2 

dt[ , identity(.SD), by = p ] 
    p q 
1: A 1 
2: B 2 

foo <- function(x) as.list(x) 
dt[ , foo(.SD), by = p ] 
    p q 
1: A 1 
2: B 2 

明顯的foo返回值被壓縮成一個data.table。我不想使用dlply,因爲它通過了分號data.tables作爲data.framesfoo,這使foo內的其他data.table操作效率低下。

+1

plyr是一個單獨的軟件包,是爲不同的數據結構之間的轉換緩解。 data.table被實現爲高效/增強的數據框架。這是它的唯一目的。所以沒有內部有效的方法來做到這一點。你已經展示過的東西(lapply)是你能做的。 – Arun

+2

你爲什麼要分割一個data.table?這違背了使用data.table的全部目的(通過避免拷貝來提高效率)。 – Roland

+0

@Roland我完全同意。也許我的例子不夠清楚。我真正想要做的是在一系列data.table子集上執行一些操作,這些操作在最後構造了一個新的'ReferenceClasses'對象,我想返回列表。 – Beasterfield

回答

3

下面是更多data.table導向的方法:

setkey(dt, p) 
dt[, list(list(dt[J(.BY[[1]])])), by = p]$V1 
#[[1]] 
# p q 
#1: A 1 
# 
#[[2]] 
# p q 
#1: B 2 

還有更多data.table風格的選擇上面,但似乎是最快的 - 在這裏與lapply的比較:

dt <- data.table(p = rep(LETTERS[1:25], 1E6), q = 25*1E6, key = "p") 
microbenchmark(dt[, list(list(dt[J(.BY[[1]])])), by = p]$V1, lapply(unique(dt$p), function(x) dt[x]), times = 10) 
#Unit: seconds 
#          expr  min  lq median  uq  max neval 
#dt[, list(list(dt[J(.BY[[1]])])), by = p]$V1 1.111385 1.508594 1.717357 1.966694 2.108188 10 
#  lapply(unique(dt$p), function(x) dt[x]) 1.871054 1.934865 2.216192 2.282428 2.367505 10 
+3

+1使用'.BY',這是'.VAR's之一,我還沒有學會如何使用。 – Frank

+0

我不喜歡這個語法,但是這最好地回答了我的問題。 – Beasterfield

+0

剛剛意識到'dt [,list(list(...)),by = p]'不僅是對我的問題的最好但完美的回答。結果列「V1」甚至可以包含任何類型的對象(基元,S3,S4,ReferenceClasses對象,...)。這就是說,我討厭的語法更多:-) – Beasterfield

2

試試這個:

> split(dt, dt[["p"]]) 
$A 
    p q 
1: A 1 

$B 
    p q 
1: B 2 
+0

哦,這很簡單:-)我只是想知道性能,因爲split不使用'data.tables'語法和功能。但你的回答實際上給了我一個正確方向的暗示。非常感謝! – Beasterfield

2

關於G.格羅騰迪克的回答我很好奇如何分割進行:

dt <- data.table(p = rep(LETTERS[1:25], 1E6), q = 25*1E6, key = "p") 

system.time(
    ll <- split(dt, dt[ ,p ]) 
) 
    user system elapsed 
    5.237 1.340 6.563 

system.time(
    ll <- lapply(unique(dt[,p]), function(x) dt[x]) 
) 
    user system elapsed 
    1.179 0.363 1.541 

所以,如果沒有更好的答案,我會跟

堅持
lapply(unique(dt[,p]), function(x) dt[x])