Почему слияния панд в python быстрее, чем слияния data.table в R в 2012 году?

160

Недавно я наткнулся на библиотеку pandas для python, которая в соответствии с этим тестом выполняет очень быстрое слияние в памяти. Это даже быстрее, чем пакет data.table в R (мой язык для анализа).

Почему pandasтак быстрее чем data.table? Это из-за присущего скорости питона преимущество над R, или есть какой-то компромисс, о котором я не знаю? Есть ли способ выполнить внутренние и внешние соединения, data.tableне прибегая к merge(X, Y, all=FALSE)и merge(X, Y, all=TRUE)?

сравнение

Вот код R и код Python используется для тестов различных пакетов.

Zach
источник
10
@JoshuaUlrich: IIRC data.tableпросто наследуется от data.frame, но он опирается на C-код под капотом.
digEmAll
4
@Joshua Что вы подразумеваете под "data.frames медленными, даже если вы манипулируете ими в C"? Это относительно чего-то еще? И медленно в чем?
Мэтт Доул
12
@JoshuaUlrich Я только что заметил, что этот комментарий никогда не укладывался в постель. Итак, чтобы прояснить это: set()был добавлен data.tableвскоре после этого обсуждения. Очень похоже на, :=но позволяет избежать небольших накладных расходов [.data.tableпри зацикливании и, следовательно, так же быстро, как matrix. Таким образом, data.frame можно манипулировать так же быстро, как матрица. Тест здесь .
Мэтт Доул
5
Можем ли мы получить обновленную версию этого эталонного теста, довольно ясно, что этот эталонный тест был действительно крайним случаем и что это уже исправлено. Учитывая, что все тесты, которые я видел, показывают, что data.table быстрее, я хотел бы узнать, что такое число слияния?
statquant
3
@statquant Я не запускал исходный тест, но мне бы очень хотелось, чтобы Уэс обновил тест.
Зак

Ответы:

120

Похоже, что Уэс, возможно, обнаружил известную проблему, data.tableкогда число уникальных строк ( уровней ) велико: 10000.

Показывает ли Rprof()большую часть времени, проведенного в вызове sortedmatch(levels(i[[lc]]), levels(x[[rc]])? Это не само объединение (алгоритм), а предварительный шаг.

В последнее время предпринимаются попытки разрешить использование символьных столбцов в ключах, что должно решить эту проблему путем более тесной интеграции с собственной глобальной хеш-таблицей строк R. Некоторые результаты тестов уже сообщаются, test.data.table()но этот код еще не подключен для замены уровней на соответствующие уровни.

Являются ли панды быстрее, чем data.tableобычные целочисленные столбцы? Это должно быть способом изолировать сам алгоритм от факторных проблем.

Кроме того, data.tableимеет в виду временные ряды . Два аспекта к этому: i) ключи, упорядоченные по нескольким столбцам, такие как (id, datetime) ii) быстрое преобладание join ( roll=TRUE) или последнее перенесенное наблюдение.

Мне нужно некоторое время, чтобы подтвердить это, поскольку я впервые увидел сравнение с data.tableпредставленным.


ОБНОВЛЕНИЕ data.table v1.8.0 выпущено в июле 2012

  • Внутренняя функция sortedmatch () удалена и заменена на chmatch () при сопоставлении уровней i с уровнями x для столбцов типа 'factor'. Этот предварительный шаг вызывал (известное) значительное замедление, когда число уровней столбца факторов было большим (например,> 10000). Усиление в тестах объединения четырех таких столбцов, как продемонстрировал Уэс МакКинни (автор пакета Python Pandas). Например, соответствие 1 миллиону строк, из которых 600 000 уникальны, теперь уменьшено с 16 до 0,5.

Также в этом выпуске было:

  • символьные столбцы теперь разрешены в ключах и предпочтительнее фактора. data.table () и setkey () больше не приводят символ к фактору. Факторы все еще поддерживаются. Реализует FR # 1493, FR # 1224 и (частично) FR # 951.

  • Новые функции chmatch () и% chin%, более быстрые версии match () и% in% для векторов символов. Используется внутренний строковый кеш R (хеш-таблица не создается). Они примерно в 4 раза быстрее, чем match () на примере в? Chmatch.

По состоянию на сентябрь 2013 года data.table на CRAN v1.8.10, а мы работаем на v1.9.0. NEWS обновляется в прямом эфире.


Но, как я написал изначально, выше:

data.tableимеет в виду временные ряды . Два аспекта к этому: i) ключи, упорядоченные по нескольким столбцам, такие как (id, datetime) ii) быстрое преобладание join ( roll=TRUE) или последнее перенесенное наблюдение.

Таким образом, Pandas equi соединение двух столбцов символов, вероятно, все еще быстрее, чем data.table. Так как он звучит так, как будто он объединяет две колонки. data.table не хеширует ключ, потому что имеет в виду преобладающие упорядоченные объединения. «Ключ» в data.table - это буквально просто порядок сортировки (аналогично кластерному индексу в SQL; т. Е. Так упорядочиваются данные в оперативной памяти). В список стоит добавить вторичные ключи, например.

Таким образом, явная разница в скорости, выделенная этим конкретным двухсимвольным тестом с более чем 10000 уникальных строк, не должна быть такой плохой, поскольку известная проблема была исправлена.

Мэтт Доул
источник
6
Если вы предоставите контрольный пример для достаточно большого и реалистичного набора данных, я с удовольствием проведу тесты. Вы также можете приветствовать. На самом деле я еще не оптимизировал код для случая с целочисленным ключом соединения (поместите его в мой список задач!), Но вы можете ожидать значительно лучшей производительности, чем строковый случай, учитывая изучение хеш-таблицы в связанной презентации.
Уэс МакКинни
22
Я не использую ни одну из этих библиотек, но рад видеть конструктивный ответ со стороны R в форме Мэтью Доула.
SlowLearner
3
Вот некоторые результаты Rprof pastie.org/3258362 . Похоже, 20-40% времени тратится в sortedmatch в зависимости от типа соединения. Придется заглянуть в целочисленные столбцы в другой раз - я сделал проблему с GitHub для панд, чтобы напомнить мне, как оптимизировать этот случай ( github.com/wesm/pandas/issues/682 )
Уэс МакКинни
14
@AndyHayden Улучшения были сделаны некоторое время назад. Я буду редактировать в новостях пунктов. Уэс выбрал один конкретный тест (равный соединению двух столбцов символов), который сыграл на этой известной проблеме. Если бы он выбрал целочисленные столбцы, все было бы иначе. И если бы он дал мне голову, прежде чем представить эталон на конференции, я мог бы рассказать ему больше об известной проблеме.
Мэтт Доул
191

Причина, по которой pandas быстрее, в том, что я придумал лучший алгоритм, который очень тщательно реализован с использованием быстрой реализации хеш-таблиц - klib и в C / Cython, чтобы избежать накладных расходов интерпретатора Python для не векторизованных частей. Алгоритм подробно описан в моей презентации: Взгляд на дизайн и разработку панд .

Сравнение с data.tableна самом деле немного интересно, потому что весь смысл R в data.tableтом, что он содержит предварительно вычисленные индексы для различных столбцов для ускорения таких операций, как выбор данных и слияния. В этом случае (объединение базы данных) DataFrame pandas не содержит предварительно вычисленной информации , которая используется для слияния, так сказать, это «холодное» слияние. Если бы я сохранил факторизованные версии ключей соединения, соединение было бы значительно быстрее - поскольку факторизация является самым узким местом для этого алгоритма.

Я также должен добавить, что внутренний дизайн DataFrame от pandas гораздо более поддается этим операциям, чем data.frame от R (который является просто внутренним списком массивов).

Уэс МакКинни
источник
76
Конечно, теперь, когда вы поняли все это на python, это должно быть легко перевести на R;)
hadley
37
Но зачем кому-то захочется? :)
Ely
9
Хм ... может быть, потому что они хотят, чтобы операции с данными были быстрее в R? Просто
угадаю
28
Привет Уэс. Похоже, что ваши результаты data.tableбыли в основном вызваны ошибкой, которая с тех пор была исправлена. Есть ли шанс, что вы сможете повторно запустить тест и написать обновленное сообщение в блоге?
Зак
6
Зак, убедитесь, что вы это проверили: github.com/Rdatatable/data.table/wiki/Benchmarks-:-Grouping
Мерик,
37

Этой теме уже два года, но кажется, что люди могут приземлиться, когда ищут сравнения панд и data.table.

Поскольку оба они развивались с течением времени, я хочу опубликовать сравнительно более новое сравнение (с 2014 года) здесь для заинтересованных пользователей: https://github.com/Rdatatable/data.table/wiki/Benchmarks-:-Grouping

Было бы интересно узнать, есть ли у Уэса и / или Мэтта (которые, кстати, являются создателями Pandas и data.table соответственно и оба прокомментировали выше) какие-либо новости, которые можно добавить сюда.

-- ОБНОВИТЬ --

Комментарий, опубликованный ниже jangorecki, содержит ссылку, которая, на мой взгляд, очень полезна: https://github.com/szilard/benchm-databases

https://github.com/szilard/benchm-databases/blob/master/plot.png

На этом графике показано среднее время операций агрегации и объединения для различных технологий ( ниже = быстрее ; сравнение в последний раз обновлялось в сентябре 2016 г.). Это было действительно познавательно для меня.

Возвращаясь к вопросу, R DT keyи R DTобратитесь к ключевидным / unkeyed вкусов R - х data.table и случаются быстрее в этом тесте , чем панд Пайтона ( Py pandas).

Merik
источник
1
Я как раз собирался опубликовать это! Спасибо за добавление.
Зак
7
@За читай это: github.com/szilard/benchm-databases, и это тоже хорошо: speakerdeck.com/szilard/…
jangorecki
1
@ За четыре года спустя наконец появились новые результаты тестов, смотрите мой ответ ниже.
Джангорецки
7

Есть отличные ответы, особенно сделанные авторами обоих инструментов, которые задают вопрос. Ответ Мэтта объясняет случай, о котором сообщается в вопросе, что он был вызван ошибкой, а не алгоритмом слияния. Ошибка была исправлена ​​на следующий день, более 7 лет назад.

В своем ответе я приведу несколько последних моментов времени операции слияния для data.table и pandas. Обратите внимание, что plyr и base R слияния не включены.

Время, которое я представляю, исходит из проекта db-benchmark , непрерывно воспроизводимого теста. Он обновляет инструменты до последних версий и повторно запускает тестовые сценарии. Он запускает много других программных решений. Если вы заинтересованы в Spark, Dask и некоторых других, обязательно проверьте ссылку.


На данный момент ... (еще предстоит реализовать: еще один объем данных и еще 5 вопросов)

Мы тестируем 2 разных размера данных таблицы LHS.
Для каждого из этих размеров данных мы запускаем 5 разных вопросов слияния.

q1: RHS- внутреннее соединение LHS- малое на целое число
q2: RHS-среда внутреннего соединения LHS на целое число
q3: RHS-среда внешнего соединения LHS на целое число
q4: RHS-среда внутреннего соединения LHS на фактор (категоричный)
q5: RHS- внутреннее соединение LHS- большой на целое число

RHS стол 3 различных размеров

  • маленький переводится в размер LHS / 1e6
  • средний переводится в размер LHS / 1e3
  • большой переводится в размер LHS

Во всех случаях между LHS и RHS имеется около 90% совпадающих строк, и в столбце присоединения RHS нет дубликатов (нет декартовых произведений).


На данный момент (запуск 2 ноября 2019 г.)

Панды 0.25.3 выпущены 1 ноября 2019 г.
data.table 0.12.7 (92abb70) выпущены 2 ноября 2019 г.

Ниже приведены значения времени в секундах для двух разных размеров данных LHS. В колонку pd2dtдобавлено поле, в котором хранится соотношение того, во сколько раз панды медленнее, чем data.table.

  • 0,5 ГБ данных LHS
+-----------+--------------+----------+--------+
| question  |  data.table  |  pandas  |  pd2dt |
+-----------+--------------+----------+--------+
| q1        |        0.51  |    3.60  |      7 |
| q2        |        0.50  |    7.37  |     14 |
| q3        |        0.90  |    4.82  |      5 |
| q4        |        0.47  |    5.86  |     12 |
| q5        |        2.55  |   54.10  |     21 |
+-----------+--------------+----------+--------+
  • 5 ГБ данных LHS
+-----------+--------------+----------+--------+
| question  |  data.table  |  pandas  |  pd2dt |
+-----------+--------------+----------+--------+
| q1        |        6.32  |    89.0  |     14 |
| q2        |        5.72  |   108.0  |     18 |
| q3        |       11.00  |    56.9  |      5 |
| q4        |        5.57  |    90.1  |     16 |
| q5        |       30.70  |   731.0  |     23 |
+-----------+--------------+----------+--------+
jangorecki
источник
Спасибо за обновление из будущего! Не могли бы вы добавить столбец для реализации R против Python для data.table?
Зак
1
Я думаю, что это хорошо, просто зайти на сайт и проверить его, даже если посмотреть на R dt vs pandas. И pyDT не был частью оригинального вопроса на самом деле.
Джангорецкий