2016-06-22 3 views
3

n 개의 데이터 테이블 (또는 데이터 프레임)을 결합하는 메모리 효율적인 방법이 있는지 궁금합니다. 나는 다음과 같은 4 data.tables이있는 경우 예를 들어, :2 개 이상의 데이터 테이블을 효율적으로 결합하십시오.

merge(df1,merge(df2,merge(df3,df4))) 

을하지만이 최적의 솔루션이 아닌 것 같아 :

df1 = data.table(group = c(1L,2L,3L),value = rnorm(3),key = "group") 
df2 = data.table(group = c(2L,1L,3L),value2 = rnorm(3),key = "group") 
df3 = data.table(group = c(3L,2L,1L),value3 = rnorm(3),key = "group") 
df4 = data.table(group = c(1L,3L,2L),value4 = rnorm(3),key = "group") 

나는과 같이 병합 할 수 있습니다. 잠재적으로 병합해야 할 많은 데이터 테이블이있을 수 있습니다. 각 연속 병합을 메모리에 복사하지 않고 위의 내용을 일반화하는 방법이 있습니까? 이 작업을 수행하기 위해 이미 data.table 외부에 허용 된 방법이 있습니까?

+1

하나의 솔루션은 다음을 병합()'감소 '사용 목록에있는 데이터의 모든 프레임을 넣어하는 것입니다. http://stackoverflow.com/questions/8091303/simultaneously-merge-multiple-data-frames-in-a-list – ulfelder

+1

'Reduce (function (x, y) x [y], list (df1, df2, df3) , df4))'는 당신이 제공 한 데이터에서 조금 더 빠른 것 같지만, 규모가 큰 것을보기 위해서 더 큰 입력에서 이것을 테스트 해봐야 할 것입니다. – nrussell

+0

@ulfelder 그건 단지 의미 론적 설탕입니다. 동일한 병합 작업이 수행됩니다. –

답변

5

데이터에 따라 가질 수있는 다른 옵션은 다음과 같습니다. 수많은 병합 작업을 수행하는 명백한 경로를 제외하면 다른 옵션은 Reduce 또는 hadley의 join_all/merge_all/wrap_em_all_up과 같이 반복됩니다.

이들은 모두 내가 사용해 왔으며 내 작업에서 더 빠른 것으로 밝혀졌지만 일반적인 벤치마킹 사례를 시도하지는 않습니다. 첫째, 일부 설정 :

DFlist = list(df1,df2,df3,df4) 
bycols = key(DFlist[[1]]) 

나는 테이블을 가정합니다은 모두 bycols에 의해 키가 있습니다.

스택.

DFlong = rbindlist(DFlist, use.names = FALSE, idcol = TRUE) 

어떤 이유로 당신이 정말로 다양한 형식의 데이터를 원하는 경우 : 각 테이블에서 새 COLS는 어떻게 든 서로 관련 모든 테이블의 동일한 위치에 표시하는 경우, 그럼 그냥 데이터를 적재 고려 , 당신은 dcast 할 수 있습니다

dcast(DFlong, 
    formula = sprintf("%s ~ .id", paste(bycols, collapse = "+")), 
    value.var = setdiff(names(DFlong), c(bycols, ".id")) 
) 

이 Data.table 및 R는하지만, 긴 형식의 데이터 가장 잘 작동합니다.

복사 항목. 당신이 bycols는 모든 테이블에 모두 같은 값을 알고 있다면, 다음 그냥 복사

DF = DFlist[[1]][, bycols, with=FALSE] 
for (k in seq_along(DFlist)){ 
    newcols = setdiff(names(DFlist[[k]]), bycols) 
    DF[, (newcols) := DFlist[[k]][, newcols, with=FALSE]] 
} 

병합 할당합니다. bycols의 일부 수준의 특정 테이블에서 누락 될 수있는 경우은, 모든 콤보와 마스터 테이블을 만들어 병합 - 양수인의 순서 수행

dplyr에서
DF = unique(rbindlist(lapply(DFlist, `[`, j = bycols, with = FALSE))) 
for (k in seq_along(DFlist)){ 
    newcols = setdiff(names(DFlist[[k]]), bycols) 
    DF[DFlist[[k]], (newcols) := mget(newcols)] 
} 
0

: 당신의 시험으로

을 모두 가지고있는 동일한 이름 (그리고 당신은 NA를 제거했습니다)을 사용하면 행에 바인딩하고 요약 할 수 있습니다.

library(dplyr) 

DF <- bind_rows(df1,df2,df3,df4) %>% 
    group_by(group) %>% 
    summarise_each(funs(na.omit)) 

그렇지 않으면 단순한 지역 최소값의 해결책이 적어도이 방언으로 코딩 자신의 양파 떨어져 몇 층 면도 저장하지만.

DF <- 
    df1 %>% 
    full_join(df2) %>% 
    full_join(df3) %>% 
    full_join(df4) 

dplyr은 S가 아닌 C++에서 실행되므로 더 빠릅니다. 불행히도 메모리 사용의 효율성에 대해 말할 수 없습니다.(비슷한 상황이 참조 : R: Updating a data frame with another data frame's dplyr sol'n를)

+1

일부 콜은 합법적 인 NA를 사용하는 경우 첫 번째 방법이 이상하게 나타날 수 있습니다. – Frank

+0

나는 그것이 NA에 어떻게 반응하는지 테스트하고있다. 다행스럽게도 문제를 발견하지 못했다. 'df3 = data.table (group = c (3L, 2L), value3 = rnorm (2), key = "group")' –

+0

NAs는 NAs를 의미합니다 :)'df3 = data.table (group = c group = c (3L, 2L, 1L), value3 = rnorm (3), key (3), key = "group") 또는 df3 = data.table = "그룹") [2, 값 3 : = NA]'. 이 두 가지 모두 내 컴퓨터에 대한 첫 번째 접근 방식에서 오류가 발생합니다. – Frank

관련 문제