2016-10-10 2 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

(i) 참조로 수정하는 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을 사용하고 결코 이러한 문제에 부딪치지 않습니다.) 지금, 당신은 당신의 체인

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

copy을 추가 할 수 있습니다하지만 당신은 사방이 작업을 수행해야 할 것 같아요.

+0

정보 주셔서 감사합니다. 그것은 기본적으로 나의 실수입니다. 나는 dtplyr 패키지가 이러한 문제를 해결할 수 있다는 잘못된 인상을 갖고있었습니다. – AntoniosK

+0

나는 (아직) 당신의 대답에 확신하지 못했습니다. 귀하의 예는 결과를 저장/인쇄하지 않으며'select()'결과를 제자리에 업데이트하지만 새로운 변수에 할당하지 않습니다. 왜냐하면'select()'결과가 어떤 변수에도 저장되지 않기 때문입니다. '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 '로 작업 할 기회가 없습니다. 내 제안은 결과를 '<-', '->'또는 '='로 저장하지 않지만 OP가 그 방법을 파악할 수 있다고 생각하거나 다른 것을 의미 했습니까? – Frank