Например (не уверен, что это наиболее репрезентативный пример):
N <- 1e6
d1 <- data.frame(x=sample(N,N), y1=rnorm(N))
d2 <- data.frame(x=sample(N,N), y2=rnorm(N))
Вот что у меня есть на данный момент:
d <- merge(d1,d2)
# 7.6 sec
library(plyr)
d <- join(d1,d2)
# 2.9 sec
library(data.table)
dt1 <- data.table(d1, key="x")
dt2 <- data.table(d2, key="x")
d <- data.frame( dt1[dt2,list(x,y1,y2=dt2$y2)] )
# 4.9 sec
library(sqldf)
sqldf()
sqldf("create index ix1 on d1(x)")
sqldf("create index ix2 on d2(x)")
d <- sqldf("select * from d1 inner join d2 on d1.x=d2.x")
sqldf()
# 17.4 sec
performance
r
join
merge
data.table
datasmurf
источник
источник
Ответы:
Подход соответствия работает, когда во втором фрейме данных есть уникальный ключ для каждого значения ключа в первом. Если во втором фрейме данных есть дубликаты, то подходы сопоставления и слияния не совпадают. Матч, конечно, быстрее, потому что он не так много. В частности, он никогда не ищет повторяющиеся ключи. (продолжение после кода)
В коде sqldf, который был опубликован в вопросе, может показаться, что индексы использовались в двух таблицах, но на самом деле они помещаются в таблицы, которые были перезаписаны до того, как SQL select когда-либо запускался, и это, отчасти, объясняет, почему это так медленно. Идея sqldf заключается в том, что фреймы данных в вашем сеансе R составляют базу данных, а не таблицы в sqlite. Таким образом, каждый раз, когда код обращается к неквалифицированному имени таблицы, он будет искать его в вашем рабочем пространстве R, а не в основной базе данных sqlite. Таким образом, показанный оператор select считывает d1 и d2 из рабочей области в основную базу данных sqlite, уничтожая те, которые были там с индексами. В результате выполняется соединение без индексов. Если вы хотите использовать версии d1 и d2, которые были в основной базе данных sqlite, вам придется называть их main.d1 и main. d2, а не как d1 и d2. Кроме того, если вы пытаетесь заставить его работать как можно быстрее, обратите внимание, что простое соединение не может использовать индексы в обеих таблицах, поэтому вы можете сэкономить время на создание одного из индексов. В приведенном ниже коде мы иллюстрируем эти моменты.
Стоит отметить, что точное вычисление может иметь огромное значение, какой пакет будет самым быстрым. Например, ниже мы делаем слияние и агрегирование. Мы видим, что результаты для этих двоих почти противоположны. В первом примере от самого быстрого к самому медленному мы получаем: data.table, plyr, merge и sqldf, тогда как во втором примере sqldf, aggregate, data.table и plyr - почти обратное первому. В первом примере sqldf в 3 раза медленнее, чем data.table, а во втором - в 200 раз быстрее, чем plyr, и в 100 раз быстрее, чем data.table. Ниже мы показываем входной код, время вывода для слияния и время вывода для агрегата. Также стоит отметить, что sqldf основан на базе данных и, следовательно, может обрабатывать объекты больше, чем может обработать R (если вы используете аргумент dbname sqldf), в то время как другие подходы ограничиваются обработкой в основной памяти. Также мы проиллюстрировали sqldf с sqlite, но он также поддерживает базы данных H2 и PostgreSQL.
Результаты двух вызовов тестов для сравнения вычислений слияния:
Результатом вызова теста производительности для сравнения агрегированных вычислений являются:
источник
132 секунды, указанные в результатах Габора, на
data.table
самом деле являются базовыми функциями синхронизацииcolMeans
иcbind
(выделение памяти и копирование, вызванное использованием этих функций). Есть и хорошие, и плохие способы использованияdata.table
.Обратите внимание, что я плохо знаю plyr, поэтому, пожалуйста, уточните у Хэдли, прежде чем полагаться на время, указанное
plyr
здесь. Также обратите внимание на то, что вdata.table
них указано время преобразованияdata.table
и установка ключа для удобства.Этот ответ был обновлен с момента первоначального ответа в декабре 2010 г. Предыдущие результаты тестов приведены ниже. Пожалуйста, просмотрите историю изменений этого ответа, чтобы узнать, что изменилось.
источник
.Internal
вызовы в пакетах CRAN, см. Политику репозитория CRAN .data.table
автоматически оптимизируетсяmean
(без.Internal
внутреннего вызова ).for
цикл, это хорошо. Не могли бы вы добавить больше информации о «SEM-анализе» к этому вопросу? Например, я предполагаю, что SEM = растровый электронный микроскоп? Информация о приложении делает его более интересным для нас и помогает нам расставлять приоритеты.Для простой задачи (уникальные значения с обеих сторон соединения) я использую
match
:Это намного быстрее, чем слияние (на моей машине от 0,13 до 3,37 с).
Мои тайминги:
merge
: 3,32 сplyr
: 0,84 сmatch
: 0,12 систочник
Подумал, было бы интересно опубликовать тест с dplyr в миксе: (много чего запущено)
Только что добавленное:
и настройте данные для dplyr с таблицей данных:
Обновлено: я удалил data.tableBad и plyr, и ничего, кроме RStudio, не было открыто (i7, 16 ГБ оперативной памяти).
С таблицей данных 1.9 и dplyr с фреймом данных:
С таблицей данных 1.9 и dplyr с таблицей данных:
Для согласованности здесь оригинал со всеми и data.table 1.9 и dplyr с использованием таблицы данных:
Я думаю, что этих данных слишком мало для новых data.table и dplyr :)
Большой набор данных:
Потребовалось около 10-13 ГБ оперативной памяти только для хранения данных перед запуском теста.
Полученные результаты:
Пробовал 1 миллиард но таран взорвал. 32 ГБ справятся без проблем.
[Edit by Arun] (dotcomken, не могли бы вы запустить этот код и вставить результаты тестирования? Спасибо).
В соответствии с запросом Аруна вот результат того, что вы предоставили мне для запуска:
Извините за путаницу, до меня дошла поздняя ночь.
Использование dplyr с фреймом данных кажется менее эффективным способом обработки сводок. Это методы для сравнения точной функциональности data.table и dplyr с включенными в них методами структуры данных? Я почти предпочел бы разделить это, так как большинство данных нужно будет очистить, прежде чем мы group_by или создадим data.table. Это может быть дело вкуса, но я думаю, что самая важная часть - насколько эффективно можно моделировать данные.
источник
Используя функцию слияния и ее необязательные параметры:
Внутреннее соединение: слияние (df1, df2) будет работать для этих примеров, потому что R автоматически объединяет кадры по общим именам переменных, но вы, скорее всего, захотите указать слияние (df1, df2, by = "CustomerId"), чтобы убедиться, что вы соответствовали только тем полям, которые вам нужны. Вы также можете использовать параметры by.x и by.y, если совпадающие переменные имеют разные имена в разных фреймах данных.
источник