Огляд
Я відносно знайомий data.table
, не так вже й багато dplyr
. Я прочитав кілька dplyr
віньєт та прикладів, які з’явились на SO, і поки що мої висновки:
data.table
іdplyr
вони порівнянні за швидкістю, за винятком випадків, коли існує багато (тобто> 10-100 К) груп, а також за інших обставин (див. орієнтири нижче)dplyr
має більш доступний синтаксисdplyr
конспекти (або заповіти) потенційних взаємодій з БД- Існують деякі незначні відмінності функціональності (див. "Приклади / використання" нижче)
На мій погляд 2. не має великої ваги, тому що я досить добре знайомий з цим data.table
, хоча я розумію, що для нових користувачів це буде великим фактором. Я хотів би уникнути аргументації щодо того, який є більш інтуїтивним, оскільки це не має значення для мого конкретного питання, заданого з точки зору когось уже знайомого data.table
. Я також хотів би уникнути дискусії про те, як "більш інтуїтивно зрозумілий" призводить до більш швидкого аналізу (безумовно, правда, але знову ж таки, не те, що мене найбільше цікавить тут).
Питання
Що я хочу знати:
- Чи є аналітичні завдання, які набагато простіше кодувати тим чи іншим пакетом для людей, знайомих з пакунками (тобто, якась комбінація натискань клавіш, необхідна в порівнянні з необхідним рівнем езотерики, де менше кожного - це добре).
- Чи є аналітичні завдання, які виконуються суттєво (тобто більше ніж 2 рази) ефективніше в одному пакеті проти іншого.
Одне з останніх запитань про так змусило мене подумати про це трохи більше, тому що до цього моменту я не думав, dplyr
що запропонує набагато більше того, що я вже можу зробити data.table
. Ось dplyr
рішення (дані наприкінці Q):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Що було набагато краще, ніж моя спроба зламати data.table
рішення. Однак, хороші data.table
рішення також дуже хороші (дякую Жан-Роберту, Арун, і тут зауважив, що я віддав перевагу єдиному твердженню щодо строго найоптимальнішого рішення):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
Синтаксис останнього може здатися дуже езотеричним, але насправді це досить просто, якщо ви звикли data.table
(тобто не використовуєте деякі більш езотеричні хитрощі).
В ідеалі я хотів би бачити це деякі приклади добре були dplyr
або data.table
спосіб значно коротший або виконує значно краще.
Приклади
Використанняdplyr
не дозволяє групувати операції, які повертають довільну кількість рядків (із запитання Eddi , зверніть увагу: це виглядає так, що він буде реалізований у dplyr 0,5 , також @beginneR показує потенційну обхідну ситуацію, використовуючиdo
відповідь на запитання @ Eddi).data.table
підтримує прокатні з'єднання (спасибі @dholstius), а також з'єднання перекриттяdata.table
внутрішньо оптимізує вирази формиDT[col == value]
абоDT[col %in% values]
для швидкості за допомогою автоматичної індексації, яка використовує двійковий пошук , використовуючи той самий синтаксис базового R. Ознайомтесь тут із деталями та крихітним орієнтиром.dplyr
пропонує стандартні версії оцінок функцій (наприкладregroup
,summarize_each_
), які можуть спростити використання програмdplyr
(використання програмного використанняdata.table
, безумовно, можливе, просто потрібно ретельно продумати, замінити / цитувати тощо, принаймні, наскільки мені відомо)
- Я запустив власні орієнтири і виявив, що обидва пакети порівнянні в аналізі стилів "розділити застосувати комбінувати", за винятком випадків, коли існує дуже велика кількість груп (> 100 К), коли точка
data.table
стає значно швидшою. - @Arun провів деякі орієнтири при приєднанні , показавши, що
data.table
масштаби краще, ніжdplyr
при збільшенні кількості груп (оновлено останніми вдосконаленнями для обох пакетів та останньою версією R). Крім того, орієнтир при спробі отримати унікальні значення наdata.table
6 разів швидше. - (Неперевірений) на
data.table
75% швидше на більших версіях групи / застосувати / сортувати, тоді якdplyr
на менших на 40% швидше ( ще одне питання щодо коментарів , дякую сьогодні). - Метт, головний автор програми
data.table
, має орієнтовані операції групуванняdata.table
,dplyr
а пітонpandas
- до 2 мільярдів рядків (~ 100 ГБ оперативної пам’яті) . - Старше тест на 80k груп має
data.table
~ 8x швидше
Дані
Це перший приклад, який я показав у розділі запитань.
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))
dplyr
і data.table
команди, і команди працюють над еталонами, тому відповідь буде в якийсь момент. # 2 (синтаксис) imO суворо помилково, але це явно заходить на територію думок, тому я голосую також за те, щоб закрити.
(d)plyr
має міру 0
dplyr
і plyr
щодо синтаксису, і в основному є основною причиною, чому мені не подобається їх синтаксис, - це те, що мені доведеться навчитися занадто багато (читати більше 1) додаткових функцій (з іменами, які все ще не майте сенсу для мене), пам’ятайте, що вони роблять, які аргументи вони приймають тощо. Це завжди було величезним відключенням для мене від філософії plyr.
.SD
). [серйозно] Я думаю, що це законні відмінності дизайну, які сподобаються різним людям
dplyr
це:as.data.table(dat)[, .SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)], by = list(name, job)]