2016-10-10 71 views
2

這是一個問題在一個更大的規模非常簡化的版本。 的目的是使用data.table結構和更快的排序和多個列分組dplyr命令。dplyr,data.table和setDT互動問題

正確的版本如下:

library(dplyr) 
library(data.table) 
library(dtplyr) 
library(lubridate) 

# data set 
dt = data.frame(id = c("a","b", "a"), 
       date = ymd(c("2016-01-03","2016-01-02","2016-01-01")), 
       value = c(10,5,9), stringsAsFactors = F) 

# process to get the id of the largest value 
(setDT(dt, key=c("id","value")) %>% select(id,value) %>% arrange(desc(value)) %>% slice(1))$id -> picked_id 

# return all rows of this id 
dt %>% filter(id %in% picked_id) 

# id   date value 
# 1: a 2016-01-01  9 
# 2: a 2016-01-03 10 

但是,當我嘗試在我的劇本不同的位置使用setDT我得到不同的結果:

dt = data.frame(id = c("a","b", "a"), 
       date = ymd(c("2016-01-03","2016-01-02","2016-01-01")), 
       value = c(10,5,9), stringsAsFactors = F) 

(dt %>% select(id,value) %>% setDT(., key=c("id","value")) %>% arrange(desc(value)) %>% slice(1))$id -> picked_id 

dt %>% filter(id %in% picked_id) 

# id  date value 
# 1 a 2016-01-03  9 
# 2 a 2016-01-02 10 

顯然,還有其他這個簡單的任務更容易理解的腳本,但我想明白爲什麼會出現這個問題。

+0

兩個'dt'變量不定義相同的數據幀。如果我使用一個,我會得到一致的結果。 –

回答

6

你不能安全地混合(我)data.table的功能,通過參考到步驟(ii)一dplyr鏈,其目的是從未被引用修改修改。看到這裏發生了什麼:

library(dplyr) 
library(data.table) 
library(dtplyr) 
library(lubridate) 

dt = data.frame(id = c("a","b", "a"), 
       date = ymd(c("2016-01-03","2016-01-02","2016-01-01")), 
       value = c(10,5,9), stringsAsFactors = FALSE) 

dt 


    id  date value 
1 a 2016-01-03 10 
2 b 2016-01-02  5 
3 a 2016-01-01  9 


dt %>% select(id,value) %>% setDT(., key=c("id","value")) 

dt 


    id  date value 
1 a 2016-01-03  9 
2 a 2016-01-02 10 
3 b 2016-01-01  5 

所以select編列已被setDT通話修改。您可以將其視爲dtplyr的實現select中的錯誤或OP的濫用。無論如何,我會一次堅持一個範式(個人而言,我只是用magrittr使用data.table,從來沒有遇到這些問題)。現在,您可以將copy添加到您的鏈條,

dt %>% select(id,value) %>% copy %>% setDT(., key=c("id","value")) 

但我猜你需要做這一切的地方。

+0

感謝您的信息。基本上這是我的錯誤。我錯誤地認爲dtplyr軟件包能夠解決這些問題。 – AntoniosK

+0

我不相信你的答案(還)。你的鏈的例子不會保存/打印結果,它會更新'select()'輸出,但不會分配給新的變量,因爲'select()'結果不會保存到任何變量中。關於'copy'也不確定,參見:'dt%>%select(id,value)%>%setDT(。,key = c(「id」,「value」)) - > ans1; dt%>%select(id,value)%>%copy%>%setDT(。,key = c(「id」,「value」)) - > ans2; all.equal(ans1,ans2)'。 – jangorecki

+0

@jangorecki我不認爲你的例子有效。第一個已經修改了'dt',所以第二個沒有機會使用原來的'dt'。我的建議不保存與''​​3210或'=',但我猜OP可以計算如何做到這一點,還是你的意思是別的東西,結果呢? – Frank