Mam plik data.frame, który chciałbym przekonwertować na listę według wierszy, co oznacza, że każdy wiersz odpowiadałby własnym elementom listy. Innymi słowy, chciałbym otrzymać listę tak długą, jak data.frame zawiera wiersze.
Do tej pory rozwiązywałem ten problem w następujący sposób, ale zastanawiałem się, czy istnieje lepszy sposób na rozwiązanie tego problemu.
xy.df <- data.frame(x = runif(10), y = runif(10))
# pre-allocate a list and fill it with a loop
xy.list <- vector("list", nrow(xy.df))
for (i in 1:nrow(xy.df)) {
xy.list[[i]] <- xy.df[i,]
}
split
każdy element ma typdata.frame with 1 rows and N columns
zamiastlist of length N
split
, prawdopodobnie powinieneś zrobićdrop=T
inaczej, twoje oryginalne poziomy czynników nie spadnąEureka!
źródło
unlist(apply(xy.df, 1, list), recursive = FALSE)
. Jednak rozwiązanie flodel jest bardziej wydajne niż użycieapply
lubt
.t
konwertuje todata.fame
na a,matrix
tak że elementy na liście są wektorami atomowymi, a nie listą zgodnie z żądaniem OP. Zwykle nie stanowi to problemu, dopóki niexy.df
zawiera mieszanych typów ...apply
. Właściwie to po prostu pętla for zaimplementowana w R.lapply
wykonuje pętlę w C, co jest znacznie szybsze. Ten format listy wierszy jest w rzeczywistości lepszy, jeśli wykonujesz dużo pętli.apply
wersja to.mapply(data.frame, xy.df, NULL)
Jeśli chcesz całkowicie nadużywać data.frame (tak jak ja) i chcesz zachować funkcjonalność $, jednym ze sposobów jest podzielenie data.frame na jednowierszowe data.frames zebrane na liście:
Jest to nie tylko intelektualna masturbacja, ale pozwala `` przekształcić '' ramkę data.frame w listę jej wierszy, zachowując indeksację $, która może być przydatna do dalszego użytku z lapply (zakładając, że funkcja, którą przekazujesz do lapply, używa tej indeksacji $)
źródło
data.frame
w jednądata.frame
?Bardziej nowoczesne rozwiązanie wykorzystuje tylko
purrr::transpose
:źródło
Pracowałem nad tym dzisiaj dla ramki data.frame (tak naprawdę data.table) z milionami obserwacji i 35 kolumnami. Moim celem było zwrócenie listy data.frames (data.tables), każda z jednym wierszem. Oznacza to, że chciałem podzielić każdy wiersz na osobną ramkę data.frame i zapisać je na liście.
Oto dwie metody, które wymyśliłem, które były około 3 razy szybsze niż w
split(dat, seq_len(nrow(dat)))
przypadku tego zestawu danych. Poniżej porównuję te trzy metody na zestawie danych z 7500 wierszami i 5 kolumnami ( tęczówka powtórzona 50 razy).To wraca
Chociaż różnice nie są tak duże jak w moim poprzednim teście,
setDF
metoda prosta jest znacznie szybsza na wszystkich poziomach dystrybucji przebiegów z max (setDF) <min (split), aattr
metoda jest zwykle ponad dwukrotnie szybsza.Czwartą metodą jest ekstremalny mistrz, który jest prostym zagnieżdżonym
lapply
, zwracającym zagnieżdżoną listę. Ta metoda ilustruje koszt tworzenia ramki data.frame z listy. Co więcej, wszystkie metody, które wypróbowałem z tądata.frame
funkcją, były mniej więcej o rząd wielkości wolniejsze niżdata.table
techniki.dane
źródło
Wydaje się, że aktualna wersja pakietu
purrr
(0.2.2) jest najszybszym rozwiązaniem:Porównajmy najciekawsze rozwiązania:
Wyniki:
Ten sam wynik możemy również uzyskać stosując
Rcpp
:Teraz porównaj z
purrr
:Wyniki:
źródło
by_row()
przeniósł się teraz dolibrary(purrrlyr)
Jeszcze kilka opcji:
Z
asplit
Z
split
irow
dane
źródło
Dla mnie najlepszym sposobem było:
Przykładowe dane:
Dzwonimy do
BBmisc
bibliotekiRezultatem będzie:
źródło
Alternatywnym sposobem jest konwersja df do macierzy, a następnie zastosowanie do niej
lappy
funkcji listy zastosuj :ldf <- lapply(as.matrix(myDF), function(x)x)
źródło
Kolejne alternatywne użycie
library(purrr)
(wydaje się być nieco szybsze w przypadku dużych ramek danych)źródło
Jak napisał @flodel: To konwertuje twoją ramkę danych na listę, która ma taką samą liczbę elementów, jak liczba wierszy w ramce danych:
Możesz dodatkowo dodać funkcję, aby wybrać tylko te kolumny, które nie są NA w każdym elemencie listy:
źródło
by_row
Funkcji zpurrrlyr
pakietu zrobi to za Ciebie.Ten przykład demonstruje
Domyślnie zwracana wartość z
myfn
jest umieszczana w nowej kolumnie listy w nazwie df.out
. Na$.out
końcu powyższej instrukcji natychmiast wybiera tę kolumnę, zwracając listę list.źródło