Dlaczego rbindlist jest "lepszy" niż rbind?
Przeglądam dokumentację data.table
, a także zauważyłem z niektórych rozmów tutaj na tak, że rbindlist
ma być lepszy niż rbind
.
Chciałbym wiedzieć, dlaczego rbindlist
jest lepszy od rbind
i w jakich scenariuszach rbindlist
naprawdę przewyższa rbind
?
Czy jest jakaś korzyść w zakresie wykorzystania pamięci?
2 answers
rbindlist
jest zoptymalizowaną wersją do.call(rbind, list(...))
, która jest znana z powolnego używania rbind.data.frame
Gdzie to się naprawdę wyróżnia
Kilka pytań, które pokazują, gdzie rbindlist
świecą
Szybkie wektorowe scalanie listy danych.frames by row
Te mają benchmarki, które pokazują, jak szybko może be.
Rbind.data.ramka jest wolna, nie bez powodu [25]}
rbind.data.frame
robi wiele sprawdzania i pasuje po nazwie. (tj. rbind.data.ramka uwzględnia fakt, że kolumny mogą być w różnych kolejnościach i dopasowywać się po nazwie), rbindlist
nie wykonuje tego rodzaju sprawdzania i połączy się według pozycji
Eg
do.call(rbind, list(data.frame(a = 1:2, b = 2:3), data.frame(b = 1:2, a = 2:3)))
## a b
## 1 1 2
## 2 2 3
## 3 2 1
## 4 3 2
rbindlist(list(data.frame(a = 1:5, b = 2:6), data.frame(b = 1:5, a = 2:6)))
## a b
## 1: 1 2
## 2: 2 3
## 3: 1 2
## 4: 2 3
Inne ograniczenia rbindlist
It used to borykać się z factors
, ze względu na błąd, który od tego czasu "fixed": {]}
Rbindlist dwa dane.tabele, w których jedna ma współczynnik a druga ma typ znakowy dla kolumny (Bug #2650)
Ma problemy z zduplikowanymi nazwami kolumn
Zobacz komunikat ostrzegawczy: w rbindlist ( allargs): NAs wprowadzony przez przymus: możliwy błąd w danych.stolik? (Bug #2384)
Rbind.data.Framework rownames może być frustrujący
rbindlist
może obsługiwać lists
data.frames
i data.tables
, i zwróci a data.tabela bez nazw wierszy
Możesz dostać się w błoto nazw wierszy za pomocą do.call(rbind, list(...))
zobacz
Jak uniknąć zmiany nazw wierszy podczas używania rbind wewnątrz do.zadzwonić?
Wydajność pamięci
W przeciwieństwie do innych typów pamięci, nie jest ona w pełni kompatybilna z innymi typami pamięci.]}rbind.data.frame
jest zaimplementowany w R
, wykonuje wiele przypisań i używa attr<-
(oraz class<-
i rownames<-
, z których wszystkie będą (wewnętrznie) Utwórz kopie utworzonych danych.rama.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:09
By v1.9.2
, rbindlist
ewoluował dość mocno, implementując wiele funkcji, w tym:]}
- wybór najwyższego
SEXPTYPE
z kolumn podczas wiązania - zaimplementowany wv1.9.2
zamknięcie FR #2456 i błąd # 4981 .- obsługa kolumn
factor
prawidłowo-najpierw zaimplementowano wv1.8.10
Zamknięcie błąd #2650 i rozszerzono do wiązania uporządkowane czynniki starannie wv1.9.2
, jak również zamknięcie FR #4856 i błąd #5019.
Ponadto, w v1.9.2
, rbind.data.table
w 1998 roku, po raz pierwszy w Polsce, pojawiła się Wersja z 1999 roku, która została wydana w 1999 roku.]}
Teraz w v1.9.3
istnieje jeszcze więcej ulepszeń na tych istniejących funkcjach:]}
rbindlist
zyskuje argumentuse.names
, który domyślnie jestFALSE
dla zgodności wstecznej.rbindlist
zyskuje również argumentfill
, który domyślnie jest równieżFALSE
dla zgodności wstecznej.- te cechy wszystkie są zaimplementowane w języku C i napisane starannie, aby nie kompromisy w szybkości podczas dodawania funkcjonalności.
- ponieważ {[2] } może teraz dopasować nazwy i wypełnić brakujące kolumny,
rbind.data.table
po prostu wywołujerbindlist
Teraz. Jedyną różnicą jest to, żeuse.names=TRUE
domyślnie dlarbind.data.table
, dla kompatybilności wstecznej.
rbind.data.frame
spowalnia trochę głównie z powodu kopii (na co wskazuje również @ mnel), których można było uniknąć (przechodząc do C). Myślę, że to nie jedyny powód. Na implementacja sprawdzania / dopasowywania nazw kolumn w rbind.data.frame
może również być wolniejsza, gdy na dane przypada wiele kolumn.ramki i jest wiele takich danych.ramki do wiązania(jak pokazano w benchmarku poniżej).
Jednakże, brak(ed) pewnych cech (takich jak sprawdzanie poziomów współczynników lub dopasowanie nazw) ma bardzo mały (lub nie) ciężar, aby był szybszy niż rbind.data.frame
. To dlatego, że zostały starannie zaimplementowane w C, zoptymalizowane pod kątem szybkości i pamięci.
Oto benchmark, który podkreśla efektywne powiązanie podczas dopasowywania nazw kolumn, a także za pomocą funkcji rbindlist
use.names
z v1.9.3
. Zestaw danych składa się z 10000 danych.ramki o rozmiarze 10*500.
UWAGA: Ten benchmark został zaktualizowany, aby uwzględnić porównanie z dplyr
's bind_rows
library(data.table) # 1.11.5, 2018-06-02 00:09:06 UTC
library(dplyr) # 0.7.5.9000, 2018-06-12 01:41:40 UTC
set.seed(1L)
names = paste0("V", 1:500)
cols = 500L
foo <- function() {
data = as.data.frame(setDT(lapply(1:cols, function(x) sample(10))))
setnames(data, sample(names))
}
n = 10e3L
ll = vector("list", n)
for (i in 1:n) {
.Call("Csetlistelt", ll, i, foo())
}
system.time(ans1 <- rbindlist(ll))
# user system elapsed
# 1.226 0.070 1.296
system.time(ans2 <- rbindlist(ll, use.names=TRUE))
# user system elapsed
# 2.635 0.129 2.772
system.time(ans3 <- do.call("rbind", ll))
# user system elapsed
# 36.932 1.628 38.594
system.time(ans4 <- bind_rows(ll))
# user system elapsed
# 48.754 0.384 49.224
identical(ans2, setDT(ans3))
# [1] TRUE
identical(ans2, setDT(ans4))
# [1] TRUE
Wiązanie kolumn jako takich bez sprawdzania nazw zajęło tylko 1,3, podczas gdy sprawdzanie nazw kolumn i odpowiednie Wiązanie zajęło tylko 1,5 sekundy więcej. W porównaniu do rozwiązania podstawowego jest to 14x szybszy i 18x szybszy od wersji dplyr
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-12 02:20:35