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?

Author: Chinmay Patil, 2013-03-28

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

Problemy z konwersją długiej listy danych.ramek (~1 mln) na pojedyncze dane.ramka za pomocą do.call and ldply

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.

 131
Author: mnel,
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 w v1.9.2 zamknięcie FR #2456 i błąd # 4981 .
  • obsługa kolumn factor prawidłowo-najpierw zaimplementowano w v1.8.10 Zamknięcie błąd #2650 i rozszerzono do wiązania uporządkowane czynniki starannie w v1.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 argument use.names, który domyślnie jest FALSE dla zgodności wstecznej.
  • rbindlist zyskuje również argument fill, 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łuje rbindlist Teraz. Jedyną różnicą jest to, że use.names=TRUE domyślnie dla rbind.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.

 36
Author: Arun,
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