Mam kod, który w jednym miejscu kończy się listą ramek danych, które naprawdę chcę przekonwertować na pojedynczą ramkę dużych danych.
Dostałem kilka wskazówek z wcześniejszego pytania, które próbowało zrobić coś podobnego, ale bardziej złożonego.
Oto przykład tego, od czego zaczynam (jest to rażąco uproszczone dla ilustracji):
listOfDataFrames <- vector(mode = "list", length = 100)
for (i in 1:100) {
listOfDataFrames[[i]] <- data.frame(a=sample(letters, 500, rep=T),
b=rnorm(500), c=rnorm(500))
}
Obecnie używam tego:
df <- do.call("rbind", listOfDataFrames)
do.call("rbind", list)
Idiom co Użyłem przed, jak również. Dlaczego potrzebujesz inicjałuunlist
?Odpowiedzi:
Użyj bind_rows () z pakietu dplyr:
źródło
.id = "column_label"
dodaje unikalne nazwy wierszy na podstawie nazw elementów listy.dplyr
jest zarówno szybkie, jak i solidne narzędzie do użycia, zmieniłem to na zaakceptowaną odpowiedź. Lata mijają!Inną opcją jest użycie funkcji plyr:
Jest to trochę wolniejsze niż oryginał:
Domyślam się, że użycie
do.call("rbind", ...)
będzie najszybszym podejściem, jakie znajdziesz, chyba że możesz zrobić coś takiego jak (a) użyć matryc zamiast data.frames i (b) wstępnie przydzielić ostateczną matrycę i przypisać do niej zamiast ją powiększać .Edytuj 1 :
Na podstawie komentarza Hadleya, oto najnowsza wersja
rbind.fill
CRAN:Jest to łatwiejsze niż rbind i nieznacznie szybsze (te czasy utrzymują się przez wiele przebiegów). I o ile rozumiem, wersja
plyr
na github jest jeszcze szybsza.źródło
I()
może zastąpićdata.frame
w twoimldply
wezwaniumelt.list
w reshape (2)do.call(function(...) rbind(..., make.row.names=F), df)
jest przydatny, jeśli nie chcesz automatycznie generowanych unikalnych nazw plików.Dla celów kompletności pomyślałem, że odpowiedzi na to pytanie wymagają aktualizacji. „Domyślam się, że użycie
do.call("rbind", ...)
będzie najszybszym podejściem, jakie można znaleźć ...” Prawdopodobnie było to prawdą w maju 2010 r. I jakiś czas później, ale około września 2011 r.rbindlist
Wprowadzono nową funkcję wdata.table
wersji pakietu 1.8.2 , z uwagą „To robi to samo codo.call("rbind",l)
, ale znacznie szybciej”. O ile szybciej?źródło
ldply
pomieścić wiązkę długich, stopionych ramek danych. W każdym razie mam niesamowite przyspieszenie dzięki twojejrbindlist
sugestii.dplyr::rbind_all(listOfDataFrames)
zrobi to samo.rbindlist
ale który dołącza ramki danych według kolumny? coś jak cbindlist?do.call()
przez 18 godzin biegałam na liście ramek danych i nadal nie skończyłam, dziękuję !!!Kod:
Sesja:
AKTUALIZACJA : Ponownie uruchom 31 stycznia 2018 r. Działa na tym samym komputerze. Nowe wersje pakietów. Dodano ziarno dla miłośników nasion.
AKTUALIZACJA : Rerun 06-sie-2019.
źródło
set.seed
), ale zauważyłem pewne różnice w wydajności w najgorszym przypadku.rbindlist
faktycznie miałem najlepszy najgorszy przypadek, a także najlepszy typowy przypadek w moich wynikachJest też
bind_rows(x, ...)
wdplyr
.źródło
Oto inny sposób, w jaki można to zrobić (po prostu dodając go do odpowiedzi, ponieważ
reduce
jest to bardzo skuteczne narzędzie funkcjonalne, które często jest pomijane jako zamiennik pętli. W tym konkretnym przypadku żadne z nich nie jest znacznie szybsze niż polecenie.)przy użyciu podstawy R:
lub za pomocą tidyverse:
źródło
Jak należy to zrobić w tidyverse:
źródło
map
jeślibind_rows
możesz wziąć listę ramek danych?Zaktualizowany wygląd dla tych, którzy chcą porównać niektóre z ostatnich odpowiedzi (chciałem porównać rozwiązanie mruczenia do rozwiązania dplyr). Zasadniczo połączyłem odpowiedzi z @TheVTM i @rmf.
Kod:
Informacje o sesji:
Wersje pakietu:
źródło
Jedyne, czego
data.table
brakuje w rozwiązaniach, to kolumna identyfikacyjna, aby dowiedzieć się, z której ramki danych na liście pochodzą dane.Coś takiego:
Ten
idcol
parametr dodaje kolumnę (.id
) identyfikującą początek ramki danych zawartej na liście. Wynik wyglądałby mniej więcej tak:źródło