обзор
Я относительно знаком с data.table, не так много с dplyr. Я прочитал несколько dplyrвиньеток и примеров, которые всплыли на SO, и до сих пор мои выводы таковы:
data.tableиdplyrсопоставимы по скорости, за исключением случаев, когда существует много (то есть> 10-100 КБ) групп, и при некоторых других обстоятельствах (см. контрольные показатели ниже)dplyrимеет более доступный синтаксисdplyrтезисы (или воля) потенциальных взаимодействий БД- Есть некоторые незначительные функциональные различия (см. «Примеры / Использование» ниже)
На мой взгляд, 2. не имеет большого веса, потому что я довольно знаком с ним data.table, хотя я понимаю, что для пользователей, новичков в обоих, это будет большой фактор. Я хотел бы избежать спора, который является более интуитивным, поскольку он не имеет отношения к моему конкретному вопросу, заданному с точки зрения кого-то, с кем уже знаком data.table. Я также хотел бы избежать дискуссии о том, как «более интуитивный» ведет к более быстрому анализу (конечно, правда, но опять же, не то, что меня больше всего интересует здесь).
Вопрос
То, что я хочу знать, это:
- Существуют ли аналитические задачи, которые намного проще кодировать с тем или иным пакетом для людей, знакомых с этими пакетами (т. Е. Требуется некоторая комбинация нажатий клавиш в сравнении с требуемым уровнем эзотерики, где меньше каждого из них - хорошая вещь).
- Существуют ли аналитические задачи, которые выполняются существенно (т.е. более чем в 2 раза) более эффективно в одном пакете по сравнению с другим.
Один недавний вопрос SO заставил меня задуматься об этом немного больше, потому что до этого момента я не думал 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не допускает сгруппированных операций, которые возвращают произвольное количество строк (из вопроса Эдди , обратите внимание: похоже, что это будет реализовано в 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.table75% быстрее на больших версиях группы / применить / сортировать и наdplyr40% быстрее на меньших ( еще один вопрос из комментариев , спасибо Данас). - Мэтт, главный автор
data.table, имеет протестированные группировка операций наdata.table,dplyrи питонpandasна срок до 2 миллиардов строк (~ 100GB в оперативной памяти) . - Старше тест на 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)]