Przegląd
Jestem względnie obeznany data.table
, ale nie bardzo dplyr
. Przeczytałem niektóre dplyr
winiety i przykłady, które pojawiły się na SO, i jak dotąd moje wnioski są następujące:
data.table
idplyr
są porównywalne pod względem prędkości, z wyjątkiem sytuacji, gdy istnieje wiele (tj.> 10–100 tys.) grup oraz w niektórych innych okolicznościach (patrz punkty odniesienia poniżej)dplyr
ma bardziej dostępną składniędplyr
streszcza (lub będzie) potencjalne interakcje DB- Istnieją pewne niewielkie różnice w funkcjonalności (patrz „Przykłady / użycie” poniżej)
Moim zdaniem 2. nie ma większego znaczenia, ponieważ jestem dość dobrze z tym zaznajomiony data.table
, choć rozumiem, że dla nowych użytkowników obu będzie to duży czynnik. Chciałbym uniknąć kłótni, która jest bardziej intuicyjna, ponieważ nie ma to znaczenia dla mojego konkretnego pytania zadanego z perspektywy kogoś, kogo już znasz data.table
. Chciałbym również uniknąć dyskusji na temat tego, w jaki sposób „bardziej intuicyjny” prowadzi do szybszej analizy (z pewnością prawda, ale znowu nie to, co mnie najbardziej interesuje).
Pytanie
Chcę wiedzieć:
- Czy istnieją zadania analityczne, które są o wiele łatwiejsze do zakodowania w jednym lub drugim pakiecie dla osób zaznajomionych z pakietami (tj. Wymagana jest kombinacja kombinacji klawiszy w porównaniu z wymaganym poziomem ezoteryzmu, gdzie mniejsza część jest dobra).
- Czy istnieją zadania analityczne, które są wykonywane znacznie (tj. Ponad 2x) bardziej efektywnie w jednym pakiecie w porównaniu do drugiego.
Jedno ostatnie pytanie SO spowodowało, że pomyślałem o tym trochę więcej, ponieważ do tego momentu nie sądziłem, dplyr
że zaoferuje coś więcej niż to, co już mogę zrobić data.table
. Oto dplyr
rozwiązanie (dane na końcu Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Co było znacznie lepsze niż moja próba hackowania data.table
rozwiązania. To powiedziawszy, dobre data.table
rozwiązania są również całkiem dobre (dzięki Jean-Robert, Arun, i zauważcie, że faworyzowałem jedno stwierdzenie nad najbardziej optymalnym rozwiązaniem):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
Składnia tego drugiego może wydawać się bardzo ezoteryczna, ale w rzeczywistości jest dość prosta, jeśli jesteś do tego przyzwyczajony data.table
(tzn. Nie używa niektórych bardziej ezoterycznych sztuczek).
Idealnie chciałbym zobaczyć kilka dobrych przykładów, w których dplyr
lub data.table
sposób jest znacznie bardziej zwięzły lub działa znacznie lepiej.
Przykłady
Stosowaniedplyr
nie zezwala na zgrupowane operacje, które zwracają dowolną liczbę wierszy (z pytania eddi , uwaga: wygląda na to, że zostanie zaimplementowane w dplyr 0.5 , również @beginneR pokazuje potencjalne obejście przy użyciudo
odpowiedzi na pytanie @ eddi).data.table
obsługuje połączenia toczne (dzięki @dholstius), a także połączenia nakładające siędata.table
wewnętrznie optymalizuje wyrażenia formieDT[col == value]
lubDT[col %in% values]
na prędkości poprzez automatyczną indeksowania który wykorzystuje przeszukiwanie binarne stosując taką samą składnię zasady R. Zobacz tutaj, aby uzyskać więcej szczegółów i mały test.dplyr
oferty standardowych wersji oceny funkcji (npregroup
,summarize_each_
), które mogą uprościć programową wykorzystaniadplyr
(uwaga programowej użytku zdata.table
jest z pewnością możliwe, tylko wymaga starannego myśli, podstawienie / cytowania itp, przynajmniej według mojej wiedzy)
- Przeprowadziłem własne testy porównawcze i stwierdziłem, że oba pakiety są porównywalne w analizie stylu „split Apply Combine”, z wyjątkiem sytuacji, gdy istnieje bardzo duża liczba grup (> 100 KB), w których moment
data.table
staje się znacznie szybszy. - @Arun przeprowadził testy porównawcze złączeń , pokazując, że
data.table
skaluje się lepiej niżdplyr
wraz ze wzrostem liczby grup (zaktualizowane o ostatnie ulepszenia w obu pakietach i najnowszą wersję R). Test porównawczy przy próbie uzyskania unikalnych wartości jestdata.table
około 6 razy szybszy. - (Niezweryfikowany) ma
data.table
75% szybciej na większych wersjach grupy / aplikuj / sortuj, podczas gdydplyr
był mniejszy o 40% na mniejszych ( kolejne pytanie SO z komentarzy , dzięki danas). - Matt, główny autor
data.table
, jest porównywana grupowania operacji nadata.table
,dplyr
a pytonpandas
na maksymalnie 2 miliardów wierszy (~ 100GB pamięci RAM) . - Starszych grup odniesienia na 80K ma
data.table
~ 8x szybciej
Dane
To jest pierwszy przykład, który pokazałem w sekcji pytań.
dat <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 2L, 2L, 2L, 2L, 2L), name = c("Jane", "Jane", "Jane", "Jane",
"Jane", "Jane", "Jane", "Jane", "Bob", "Bob", "Bob", "Bob", "Bob",
"Bob", "Bob", "Bob"), year = c(1980L, 1981L, 1982L, 1983L, 1984L,
1985L, 1986L, 1987L, 1985L, 1986L, 1987L, 1988L, 1989L, 1990L,
1991L, 1992L), job = c("Manager", "Manager", "Manager", "Manager",
"Manager", "Manager", "Boss", "Boss", "Manager", "Manager", "Manager",
"Boss", "Boss", "Boss", "Boss", "Boss"), job2 = c(1L, 1L, 1L,
1L, 1L, 1L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 0L)), .Names = c("id",
"name", "year", "job", "job2"), class = "data.frame", row.names = c(NA,
-16L))
źródło
dplyr
to:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]
dplyr
idata.table
zespoły pracują nad testami porównawczymi, więc w pewnym momencie pojawi się odpowiedź. # 2 (składnia) imO jest ściśle fałszywe, ale to wyraźnie wkracza na terytorium opinii, więc głosuję również za zamknięciem.(d)plyr
ma miarę 0dplyr
iplyr
jeśli chodzi o składnię i jest w zasadzie główny powód, dlaczego nie lubię ich składni, jest to, że muszę nauczyć się zbyt wiele (więcej niż 1) dodatkowe funkcje (z nazwami, które nadal nie mają dla mnie sensu), pamiętajcie, co robią, jakie argumenty biorą itp. To zawsze było dla mnie wielkim odejściem od filozofii plyr..SD
.) tajemnicze skróty . [poważnie] Myślę, że są to uzasadnione różnice projektowe, które przypadną doOdpowiedzi:
Musimy zajmować co najmniej te elementy, aby zapewnić kompleksową odbierania / porównanie (w przypadkowej kolejności ważności):
Speed
,Memory usage
,Syntax
iFeatures
.Moim zamiarem jest objęcie każdego z nich tak jasno, jak to możliwe z perspektywy tabeli data.tab.
Składnia data.table jest spójna w swojej formie -
DT[i, j, by]
. Aby utrzymaći
,j
aby
razem jest zgodne z projektem. Utrzymując powiązane operacje razem, pozwala łatwo zoptymalizować operacje pod kątem szybkości i, co ważniejsze, wykorzystania pamięci , a także zapewnia pewne zaawansowane funkcje , a wszystko to przy zachowaniu spójności składni.1. Prędkość
Do pytania, które już pokazuje dane, dodano kilka testów porównawczych (choć głównie dotyczących operacji grupowania). Tabela staje się szybsza niż dplyr wraz ze wzrostem liczby grup i / lub wierszy do grupowania, w tym testy porównawcze według Matta przy grupowaniu od 10 milionów do 2 miliardy wierszy (100 GB w pamięci RAM) w 100–10 milionach grup i różnych kolumnach grupujących, co również jest porównywalne
pandas
. Zobacz także zaktualizowane testy porównawcze , które obejmująSpark
ipydatatable
również.Jeśli chodzi o testy porównawcze, dobrze byłoby objąć również pozostałe aspekty:
Operacje grupowania obejmujące podzbiór wierszy - tj
DT[x > val, sum(y), by = z]
. Operacje typu.Benchmark innych operacji, takich jak aktualizacja i dołączenia .
Poza tym środowisko wykonawcze stanowi również ślad pamięci dla każdej operacji.
2. Wykorzystanie pamięci
Operacje obejmujące
filter()
lubslice()
w dplyr mogą być nieefektywne pamięci (zarówno na data.frames, jak i data.tables). Zobacz ten post .Interfejs data.table pozwala w tej chwili modyfikować / aktualizować kolumny przez odniesienie (zauważ, że nie musimy ponownie przypisywać wyniku do zmiennej).
Ale dplyr nigdy nie będzie aktualizowany przez odniesienie. Odpowiednikiem dplyr byłoby (zauważ, że wynik musi zostać ponownie przypisany):
Problemem jest przejrzystość referencyjna . Aktualizacja obiektu data.table przez odwołanie, szczególnie w obrębie funkcji, może nie zawsze być pożądana. Ale jest to niezwykle przydatna funkcja: zapoznaj się z tym i tymi postami w interesujących przypadkach. I chcemy to zachować.
Dlatego pracujemy nad
shallow()
funkcją eksportu do data.table, która zapewni użytkownikowi obie możliwości . Na przykład, jeśli pożądane jest, aby nie modyfikować tabeli danych wejściowych w ramach funkcji, można wtedy:Nieużywanie
shallow()
powoduje zachowanie starej funkcjonalności:Tworząc płytką kopię przy użyciu
shallow()
, rozumiemy, że nie chcesz modyfikować oryginalnego obiektu. Dbamy o wszystko wewnętrznie, aby zapewnić, że jednocześnie kopiując kolumny, modyfikujesz tylko wtedy, gdy jest to absolutnie konieczne . Po wdrożeniu powinno to całkowicie rozwiązać kwestię przejrzystości odniesienia, jednocześnie zapewniając użytkownikowi obie możliwości.Agreguj podczas dołączania:
Załóżmy, że masz dwie tabele danych w następujący sposób:
I chciałbyś dostać się
sum(z) * mul
do każdego wierszaDT2
podczas łączenia kolumnx,y
. Możemy:1) agreguj,
DT1
aby uzyskaćsum(z)
, 2) wykonaj łączenie i 3) pomnóż (lub)2) zrób to wszystko za jednym razem (używając
by = .EACHI
funkcji):Jaka jest zaleta?
Nie musimy przydzielać pamięci dla wyniku pośredniego.
Nie musimy grupować / mieszać dwa razy (jeden w celu agregacji, a drugi w celu dołączenia).
A co ważniejsze, operacja, którą chcieliśmy wykonać, jest jasna, patrząc na
j
(2).Sprawdź ten post, aby uzyskać szczegółowe wyjaśnienie
by = .EACHI
. Nie pojawiają się żadne wyniki pośrednie, a agregacja + agregacja jest wykonywana za jednym razem.Spójrz na to , to i to posty na prawdziwe scenariusze użytkowania.
W
dplyr
musisz najpierw połączyć i agregować lub agregować, a następnie łączyć , z których żadne nie jest tak wydajne pod względem pamięci (co z kolei przekłada się na szybkość).Zaktualizuj i dołącza:
Rozważ poniższy kod data.table:
dodaje / aktualizuje
DT1
kolumnęcol
zmul
zDT2
tych wierszy, w którychDT2
kluczowa kolumna pasujeDT1
. Nie sądzę, że istnieje dokładny odpowiednik tej operacji wdplyr
, tj. Bez unikania*_join
operacji, która musiałaby skopiować całąDT1
tylko, aby dodać do niej nową kolumnę, co jest niepotrzebne.Sprawdź ten post, aby zobaczyć prawdziwy scenariusz użytkowania.
3. Składnia
Spójrzmy teraz na składnię . Hadley skomentował tutaj :
Uważam tę uwagę za bezcelową, ponieważ jest ona bardzo subiektywna. Być może możemy spróbować porównać spójność w składni . Porównamy składnię data.table i dplyr obok siebie.
Będziemy pracować z danymi atrapa pokazanymi poniżej:
Podstawowe operacje agregacji / aktualizacji.
Składnia data.table jest zwarta, a dplyr dość gadatliwy. Sprawy są mniej więcej równoważne w przypadku (a).
W przypadku (b) musieliśmy użyć
filter()
w dplyr podczas podsumowania . Ale podczas aktualizacji musieliśmy przenieść logikę do środkamutate()
. Jednak w data.table wyrażamy obie operacje z tą samą logiką - operujemy na wierszach, gdziex > 2
, ale w pierwszym przypadku, otrzymujemysum(y)
, podczas gdy w drugim przypadku aktualizujemy te wierszey
o ich skumulowaną sumę.To mamy na myśli, gdy mówimy, że
DT[i, j, by]
forma jest spójna .Podobnie w przypadku (c), kiedy mamy
if-else
warunek, jesteśmy w stanie wyrazić logikę „taką, jaka jest” zarówno w data.table, jak i dplyr. Jeśli jednak chcielibyśmy zwrócić tylko te wiersze, w którychif
warunek jest spełniony, i pominąć inaczej, nie możemy użyćsummarise()
bezpośrednio (AFAICT). Musimyfilter()
najpierw, a następnie podsumować, ponieważsummarise()
zawsze oczekuje jednej wartości .Chociaż zwraca ten sam wynik, użycie
filter()
tutaj powoduje, że faktyczna operacja jest mniej oczywista.Równie dobrze może być możliwe zastosowanie
filter()
w pierwszym przypadku (nie wydaje mi się to oczywiste), ale chodzi mi o to, że nie powinniśmy.Agregacja / aktualizacja w wielu kolumnach
W przypadku (a) kody są mniej więcej równoważne. data.table korzysta ze znanej funkcji bazowej
lapply()
, natomiastdplyr
wprowadza*_each()
wraz z szeregiem funkcji dofuns()
.data.table
:=
wymaga podania nazw kolumn, podczas gdy dplyr generuje je automatycznie.W przypadku (b) składnia dplyr jest stosunkowo prosta. Poprawianie agregacji / aktualizacji wielu funkcji znajduje się na liście data.table.
W przypadku (c) dplyr zwróci
n()
tyle razy tyle kolumn, ile tylko raz. W data.table wszystko, co musimy zrobić, to zwrócić listęj
. Każdy element listy stanie się kolumną w wyniku. Możemy więc ponownie użyć znanej funkcji bazowej,c()
aby połączyć.N
się z wartością,list
która zwraca alist
.Łączy się
dplyr zapewnia osobne funkcje dla każdego rodzaju złączenia, w którym as data.table umożliwia sprzężenia przy użyciu tej samej składni
DT[i, j, by]
(i z uzasadnieniem). Zapewnia również równoważnąmerge.data.table()
funkcję jako alternatywa.Niektórzy mogą znaleźć osobną funkcję dla każdego połączenia o wiele ładniejszą (lewą, prawą, wewnętrzną, anty, pół itd.), Podczas gdy inni mogą lubić tabelę danych.
DT[i, j, by]
Lubmerge()
podobny do bazy R.Jednak dołączenia dplyr właśnie to robią. Nic więcej. Nic mniej.
data.tables może wybierać kolumny podczas łączenia (2), aw dplyr musisz
select()
najpierw połączyć obie data.frame przed dołączeniem, jak pokazano powyżej. W przeciwnym razie zmaterializujesz połączenie z niepotrzebnymi kolumnami, aby usunąć je później, a to będzie nieefektywne.data.tables można agregować podczas łączenia (3), a także aktualizować podczas łączenia (4), używając
by = .EACHI
funkcji. Po co materializować cały wynik łączenia, aby dodać / zaktualizować tylko kilka kolumn?data.table ma możliwość toczenia złączeń (5) - roll do przodu, LOCF , roll do tyłu, NOCB , najbliższe .
data.table ma również
mult =
argument, który wybiera pierwsze , ostatnie lub wszystkie dopasowania (6).data.table ma
allow.cartesian = TRUE
argument chroniący przed przypadkowymi nieprawidłowymi połączeniami.do()
...Podsumowanie dplyr jest specjalnie zaprojektowane dla funkcji, które zwracają jedną wartość. Jeśli funkcja zwraca wiele / nierówne wartości, będziesz musiał skorzystać z tej opcji
do()
. Musisz wcześniej wiedzieć o wszystkich zwracanych wartościach wszystkich funkcji..SD
ekwiwalentem jest.
W data.table możesz wrzucić prawie wszystko
j
- jedyną rzeczą do zapamiętania jest zwrócenie listy, aby każdy element listy został przekonwertowany na kolumnę.W Dplyr nie mogę tego zrobić.
do()
Musisz uciekać się do tego, czy masz pewność, że funkcja zawsze zwróci jedną wartość. I to jest dość powolne.Spójrz na to SO pytanie i to . Zastanawiam się, czy byłoby możliwe wyrażenie odpowiedzi tak prosto, używając składni dplyr ...
4. Funkcje
Wskazałem większość funkcji tutaj, a także w tym poście. Dodatkowo:
fread - szybki czytnik plików jest już dostępny od dawna.
fwrite - parallelised szybko plik pisarz jest już dostępna. Zobacz ten post, aby uzyskać szczegółowe wyjaśnienie dotyczące implementacji i # 1664, aby śledzić dalsze zmiany.
Automatyczne indeksowanie - kolejna przydatna funkcja do optymalizacji wewnętrznej składni R.
Grupowanie ad-hoc :
dplyr
automatycznie sortuje wyniki poprzez grupowanie zmiennych podczassummarise()
, co może nie zawsze być pożądane.Liczne zalety złączeń data.table (dla szybkości / wydajności pamięci i składni) wspomnianych powyżej.
Złączenia
<=, <, >, >=
inne niż Equi : Umożliwia łączenia za pomocą innych operatorów wraz ze wszystkimi innymi zaletami połączeń data.table.Niedawno zaimplementowano nakładające się łączenia zakresów w data.table. Sprawdź ten post, aby zapoznać się z testami porównawczymi.
setorder()
funkcja w data.table, która pozwala na naprawdę szybkie zmienianie kolejności data.tables przez odniesienie.dplyr zapewnia interfejs do baz danych przy użyciu tej samej składni, czego nie ma obecnie data.table.
data.table
zapewnia szybsze odpowiedniki zestaw operacji (napisany przez Jana Góreckiego) -fsetdiff
,fintersect
,funion
afsetequal
z dodatkowymall
argumentem (jak w SQL).data.table obciążenia czysto bez ostrzeżenia maskowania i posiada mechanizm opisany tutaj dla
[.data.frame
kompatybilności kiedy przeszedł do dowolnego pakietu R. dplyr zmiany funkcji bazowychfilter
,lag
i[
która może być przyczyną problemów; np. tu i tutaj .Wreszcie:
W bazach danych - nie ma powodu, dla którego data.table nie może zapewnić podobnego interfejsu, ale teraz nie jest to priorytet. Może się zdarzyć, że użytkownicy bardzo polubią tę funkcję ... nie jestem pewien.
O równoległości - wszystko jest trudne, dopóki ktoś nie zrobi tego. Oczywiście będzie to wymagało wysiłku (bezpieczeństwo wątku).
OpenMP
.źródło
:=
),dplyr
odpowiednik powinien być również używany<-
jakDF <- DF %>% mutate...
zamiast zamiastDF %>% mutate...
dplyr
może to być łatwiejsze dla użytkowników, którzy używaliplyr
składni, aledata.table
może być łatwiejsze dla użytkowników, którzy używali zapytań o podobną składnię językowąSQL
, oraz związaną z tym algebrę relacyjną, która dotyczy transformacji danych tabelarycznych. @Arun należy zauważyć, że operatory zestawu są bardzo łatwe do wykonania dziękidata.table
funkcji owijania i oczywiście przynosi znaczne przyspieszenie.Oto moja próba wyczerpującej odpowiedzi z perspektywy duszy, zgodnie z ogólnym zarysem odpowiedzi Aruna (ale nieco zmieniona w oparciu o różne priorytety).
Składnia
Składnia jest subiektywna, ale podtrzymuję moje stwierdzenie, że zwięzłość tabeli data.t utrudnia naukę i jest trudniejsza do odczytania. Wynika to częściowo z tego, że dplyr rozwiązuje znacznie łatwiejszy problem!
Jedną z naprawdę ważnych rzeczy, które robi dla ciebie dplyr, jest to, że ogranicza twoje opcje. Twierdzę, że większość problemów z pojedynczą tabelą można rozwiązać za pomocą tylko pięciu czasowników filtrujących, wybierających, mutujących, aranżujących i podsumowujących, wraz z przysłówkiem „według grupy”. To ograniczenie jest dużą pomocą podczas nauki manipulacji danymi, ponieważ pomaga uporządkować myślenie o problemie. W dplyr każdy z tych czasowników jest odwzorowany na pojedynczą funkcję. Każda funkcja wykonuje jedno zadanie i jest łatwa do zrozumienia w izolacji.
Złożoność tworzysz, łącząc ze sobą te proste operacje
%>%
. Oto przykład jednego z postów połączonych z Arun :Nawet jeśli nigdy wcześniej nie widziałeś dplyr (lub nawet R!), Nadal możesz uzyskać sedno tego, co się dzieje, ponieważ wszystkie funkcje są angielskimi czasownikami. Wadą angielskich czasowników jest to, że wymagają więcej pisania niż
[
, ale myślę, że można to w dużej mierze złagodzić dzięki lepszemu autouzupełnianiu.Oto równoważny kod data.table:
Trudniej jest podążać za tym kodem, chyba że znasz już dane.tabela. (Nie mogłem też wymyślić, jak wciąć powtórzenie
[
w sposób, który wygląda dobrze dla mojego oka). Osobiście, kiedy patrzę na kod, który napisałem 6 miesięcy temu, to tak, jakby patrzeć na kod napisany przez nieznajomego, więc wolę prosty, jeśli szczegółowy, kod.Dwa inne drobne czynniki, które moim zdaniem nieznacznie zmniejszają czytelność:
Ponieważ wykorzystuje się prawie każdą operację na tabeli danych
[
, potrzebny jest dodatkowy kontekst, aby dowiedzieć się, co się dzieje. Na przykład, czyx[y]
łączysz dwie tabele danych czy wyodrębniasz kolumny z ramki danych? To tylko niewielki problem, ponieważ w dobrze napisanym kodzie nazwy zmiennych powinny sugerować, co się dzieje.Podoba mi się, że
group_by()
to osobna operacja w Dplyr. Zasadniczo zmienia obliczenia, więc myślę, że powinno być oczywiste podczas przeglądania kodu, i łatwiej jest go dostrzecgroup_by()
niżby
argument[.data.table
.Podoba mi się również to, że fajka nie ogranicza się tylko do jednej paczki. Możesz zacząć od uporządkowania swoich danych za pomocą tidyr , a skończyć z fabułą w ggvis . I nie jesteś ograniczony do pakietów, które piszę - każdy może napisać funkcję, która stanowi płynną część potoku manipulacji danymi. W rzeczywistości wolę poprzedni kod data.table przepisany za pomocą
%>%
:A pomysł z rurociągów
%>%
nie jest ograniczone tylko do ramek danych i jest łatwo uogólnić na innych kontekstach interaktywnych grafik internetowych , web skrobanie , GIST , umów run-time , ...)Pamięć i wydajność
Zebrałem je razem, ponieważ dla mnie nie są one tak ważne. Większość użytkowników R pracuje z mniej niż 1 milionem wierszy danych, a dplyr jest wystarczająco szybki, aby uzyskać taki rozmiar danych, że nie jesteś świadomy czasu przetwarzania. Optymalizujemy dplyr pod kątem ekspresji na średnich danych; nie krępuj się użyć data.table, by uzyskać surową prędkość na większych danych.
Elastyczność programu dplyr oznacza również, że można łatwo dostosować parametry wydajności przy użyciu tej samej składni. Jeśli wydajność dplyr z backendem ramki danych nie jest dla ciebie wystarczająco dobra, możesz użyć backendu data.table (choć z nieco ograniczonym zestawem funkcji). Jeśli dane, z którymi pracujesz, nie mieszczą się w pamięci, możesz użyć zaplecza bazy danych.
To powiedziawszy, wydajność dplyr poprawi się w dłuższej perspektywie. Zdecydowanie zaimplementujemy niektóre z świetnych pomysłów dotyczących data.table, takich jak porządkowanie radix i używanie tego samego indeksu dla połączeń i filtrów. Pracujemy również nad równoległością, abyśmy mogli skorzystać z wielu rdzeni.
funkcje
Kilka rzeczy, nad którymi planujemy pracować w 2015 roku:
readr
pakiet, aby go łatwo dostać plików z dysku iw pamięci, analogicznie dofread()
.Bardziej elastyczne połączenia, w tym obsługa połączeń innych niż równorzędne.
Bardziej elastyczne grupowanie, takie jak próbki bootstrap, rollupy i więcej
Inwestuję też czas w ulepszanie łączników bazy danych R , możliwość komunikowania się z aplikacjami internetowymi i ułatwianie skrobania stron HTML .
źródło
data.table
składnię), ale możesz łatwo użyć%>%
, aby potokowaćdata.table
operacje, jeśli nie lubisz[
stylu.%>%
nie jest specyficznedplyr
, raczej pochodzi z osobnego pakietu (którego jesteś też współautorem), więc nie jestem pewien, czy rozumiem, co próbujesz powiedzieć w większości akapitów składni .%>%
z data.tableDT[\n\texpression\n][\texpression\n]
( gist ), co w rzeczywistości działa całkiem dobrze. Trzymam odpowiedź Arun jako odpowiedź, kiedy bardziej bezpośrednio odpowiada na moje pytania szczegółowe, które nie są tak bardzo o dostępności składni, ale myślę, że to dobre rozwiązanie dla ludzi, którzy próbują uzyskać ogólne wyczucie różnic / podobieństw pomiędzydplyr
idata.table
.fread()
? Czy nie lepiej byłoby spędzać czas na ulepszaniu fread () lub pracowaniu nad innymi (słabo rozwiniętymi) rzeczami?data.table
opiera się na masowym nadużywaniu[]
notacji. To jest jego największa siła i największa słabość.W bezpośredniej odpowiedzi na tytuł pytania ...
dplyr
zdecydowanie robi rzeczy,data.table
których nie można.Twój punkt # 3
jest bezpośrednią odpowiedzią na twoje pytanie, ale nie jest podniesiony do wystarczająco wysokiego poziomu.
dplyr
jest naprawdę rozszerzalnym interfejsem do wielu mechanizmów przechowywania danych, gdziedata.table
jest rozszerzeniem do jednego.Spójrz na
dplyr
interfejs agnostyczny zaplecza, w którym wszystkie cele używają tego samego gramatyki, gdzie możesz dowolnie rozszerzać cele i programy obsługi.data.table
zdplyr
perspektywy jest jednym z tych celów.Nigdy (mam nadzieję) nie zobaczysz dnia, w którym
data.table
spróbujesz przetłumaczyć twoje zapytania, aby utworzyć instrukcje SQL działające z dyskowymi lub sieciowymi magazynami danych.dplyr
może zrobić rzeczydata.table
, których nie zrobi lub nie.Opierając się na konstrukcji działającej w pamięci,
data.table
może mieć znacznie trudniejszy czas, rozszerzając się na równoległe przetwarzanie zapytań niżdplyr
.W odpowiedzi na pytania w ciele ...
Stosowanie
To może wydawać się wykopem, ale prawdziwa odpowiedź brzmi „nie”. Ludzie zaznajomieni z narzędziami wydają się korzystać z tego, który jest im najbardziej znany, lub takiego, który jest właściwy dla danego zadania. Biorąc to pod uwagę, czasami chcesz zaprezentować konkretną czytelność, czasem poziom wydajności, a gdy potrzebujesz wystarczająco wysokiego poziomu obu, możesz potrzebować innego narzędzia, aby dostosować się do tego, co już musisz zrobić wyraźniejsze abstrakty .
Wydajność
Znowu nie.
data.table
wyróżnia się wydajnością we wszystkim, co robi, gdziedplyr
ogranicza się pod pewnymi względami do bazowego magazynu danych i zarejestrowanych procedur obsługi.Oznacza to, że gdy napotkasz problem z wydajnością
data.table
, możesz być całkiem pewien, że jest to funkcja zapytania, a jeśli faktycznie jest to wąskie gardłodata.table
, to zyskałeś radość ze złożenia raportu. Dotyczy to również sytuacji, gdydplyr
jest używanydata.table
jako back-end; Państwo mogą zobaczyć jakiś narzut zdplyr
ale kursy są to zapytanie.Gdy
dplyr
występują problemy z wydajnością back-endów, można je obejść, rejestrując funkcję do oceny hybrydowej lub (w przypadku baz danych) manipulując wygenerowanym zapytaniem przed wykonaniem.Zobacz także zaakceptowaną odpowiedź na pytanie, kiedy plyr jest lepszy niż data.table?
źródło