2013-02-25 12 views
10

mam listę zawierającą ramki danych jako jego elementów R.Jak scalić wszystkie elementy listy w R?

przykład:

df1 <- data.frame("names"=c("John","Sam","Dave"),"age"=c(21,22,25)) 
df2 <- data.frame("names"=c("John","Sam"),"score"=c(22,25)) 
df3 <- data.frame("names"=c("John","Sam","Dave"),"country"=c("US","SA","NZ")) 
mylist <- list(df1,df2,df3) 

jest możliwe połączenie wszystkich elementów wypożyczane sobą bez użycia pętli?

Moje życzenia wyjścia dla tego przykładu jest:

names age score country 
1 John 21 22  US 
2 Sam 22 25  SA 

Lista w tym przykładzie ma tylko trzy elementy; jednak szukam rozwiązania, które poradzi sobie z dowolną liczbą elementów.

Odpowiedz

16

Można użyć Reduce jedno rozwiązanie Wkład:

Reduce(merge,mylist) 

    names age score country 
1 John 21 22  US 
2 Sam 22 25  SA 
7

Szybki i brudny przykład:

merge(merge(df1, df2),df3) 

EDIT - Bardzo podobne pytanie tutaj: Simultaneously merge multiple data.frames in a list

rozwiązanie:

merged.data.frame = Reduce(function(...) merge(..., all=F), my.list) 

Zastrzeżone - All I zmieniło od @Charles odpowiedź brzmiała: merge(..., all=F) zamiast T - w ten sposób daje pożądany wynik.

+0

Dzięki @alexwhan. Powinienem być bardziej konkretny. Potrzebuję rozwiązania dla listy z dowolną liczbą elementów. Moja lista wejściowa może mieć za każdym razem inną liczbę elementów zamiast trzech w tym przykładzie. – user2109248

+0

Tak, właśnie to się zastanawiałem – alexwhan

3

po prostu pokazać, że można to zrobić w inny sposób ...

mymerge <- function(mylist) { 
    names(mylist) <- sapply(mylist, function(x) names(x)[2]) 
    ns <- unique(unlist(lapply(mylist, function(x) levels(x$names)))) 
    as.data.frame(c(list(names=ns), lapply(mylist, function(x) 
         {x[match(ns, x$names),2]}))) 
} 

> mymerge(mylist) 
    names age score country 
1 Dave 25 NA  NZ 
2 John 21 22  US 
3 Sam 22 25  SA 

Można by łatwo przystosować do usuwania wierszy z brakującymi wartościami, lub może po prostu usunąć później z complete.cases.

Aby pokazać, że jest szybszy, przygotujemy większy zestaw danych; 100 zmiennych i 25 nazw.

set.seed(5) 
vs <- paste0("V", 1:100) 
mylist <- lapply(vs, function(v) { 
    x <- data.frame(names=LETTERS[1:25], round(runif(25, 0,100))) 
    names(x)[2] <- v 
    x 
}) 

> microbenchmark(Reduce(merge, mylist), myf(mylist)) 
Unit: milliseconds 
        expr  min  lq median  uq  max 
1   myf(mylist) 12.81371 13.19746 13.36571 14.40093 33.90468 
2 Reduce(merge, mylist) 199.23714 206.28608 207.30247 208.44939 226.05980 
+0

Cóż, rzadko jestem brana z góry. Nie, że nie zasługuję na to, ale komentarz byłby miły. Myślałem, że to całkiem sprytne i będzie szybsze niż "Zmniejsz", ​​gdy dane staną się większe, jak pokazano w edycji. – Aaron

+0

+1 za benchmark! Zmniejszenie jest naprawdę powolne! – agstudy