2015-10-28 3 views
4

Предположим, что у меня есть структура списка, где есть data.frames, вложенные в каждый элемент.R: Объединение вложенных элементов списка по имени

l <- list(A = list(D = data.frame(V1 = seq(3), V2 = LETTERS[1:3]), 
        E = data.frame(V1 = seq(3), V2 = LETTERS[4:6])), 
      B = list(D = data.frame(V1 = seq(3), V2 = LETTERS[7:9]), 
        E = data.frame(V1 = seq(3), V2 = LETTERS[10:12]))) 

$A 
$A$D 
    V1 V2 
1 1 A 
2 2 B 
3 3 C 

$A$E 
    V1 V2 
1 1 D 
2 2 E 
3 3 F 


$B 
$B$D 
    V1 V2 
1 1 G 
2 2 H 
3 3 I 

$B$E 
    V1 V2 
1 1 J 
2 2 K 
3 3 L 

Я хотел бы найти способ объединить D и Edata.frames соответственно из элементов родительского списка (A, B), так что результат будет выглядеть так:

$D 
    V1 V2 
1 1 A 
2 2 B 
3 3 C 
4 1 G 
5 2 H 
6 3 I 

$E 
    V1 V2 
1 1 D 
2 2 E 
3 3 F 
4 1 J 
5 2 K 
6 3 L 

я могу выполнить это с петлей, но я пытаюсь найти что-то более эффективное/элегантное.

out <- vector("list", length(list)) 
for(i in c("D","E")){ 
    out[[i]] <- do.call("rbind", lapply(l, function(x) x[[i]])) 
} 

ответ

4

Мы сплющить вложенную list к одному list с 4 элементов (l1), то split «l1» по именам «l1» после замены префикса части до . использования sub. Затем rbind вложенный list с использованием do.call.

l1 <- do.call('c', l) 
lapply(split(l1,sub('.*\\.', '', names(l1))), 
         function(x) do.call(rbind, x)) 

Это может быть также сделано с purrr и dplyr

library(purrr) 
library(dplyr) 
transpose(l) %>% 
      map(bind_rows) 
#$D 
#Source: local data frame [6 x 2] 

#  V1 V2 
# (int) (chr) 
#1  1  A 
#2  2  B 
#3  3  C 
#4  1  G 
#5  2  H 
#6  3  I 

#$E 
#Source: local data frame [6 x 2] 

#  V1 V2 
# (int) (chr) 
#1  1  D 
#2  2  E 
#3  3  F 
#4  1  J 
#5  2  K 
#6  3  L 
+0

Приятно, не могли бы вы немного объяснить регулярное выражение? Я не так хорошо знаком с этим. – cdeterman

3

Я не знаю, если это более эффективно:

l1 <- unlist(l, recursive = FALSE) 
D <- do.call(rbind, l1[grepl("\\.D", names(l1))]) 
E <- do.call(rbind, l1[grepl("\\.E", names(l1))]) 

Если важно, вы должны были бы исправить имена строк впоследствии.

3

Я хотел бы использовать более элегантный подход с data.table (не обязательно более эффективной):

library(data.table) 

lapply(c('E','D'), function(u) rbindlist(lapply(l, `[[`, u))) 
#$A 
# V1 V2 
#1: 1 D 
#2: 2 E 
#3: 3 F 
#4: 1 J 
#5: 2 K 
#6: 3 L 

#$B 
# V1 V2 
#1: 1 A 
#2: 2 B 
#3: 3 C 
#4: 1 G 
#5: 2 H 
#6: 3 I 

В основании R это можно сделать с помощью

lapply(c('E','D'), function(u) do.call(rbind, lapply(l, `[[`, u))) 
Смежные вопросы