Чому панди зливаються в python швидше, ніж злиття data.table в R у 2012 році?


160

Нещодавно я натрапив на бібліотеку панди для python, яка відповідно до цього орієнтиру виконує дуже швидкі злиття в пам'яті. Це навіть швидше, ніж пакет data.table в R (мою мову для вибору для аналізу).

Чому pandasтак швидше, ніж data.table? Це через притаманну перевагу швидкості в пітоні над R, чи є якийсь компроміс, про який я не знаю? Чи є спосіб виконати внутрішнє і зовнішнє з'єднання, data.tableне вдаючись до merge(X, Y, all=FALSE)і merge(X, Y, all=TRUE)?

Порівняння

Ось код R і код Python, який використовується для порівняння різних пакетів.


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 швидше, я хотів би побачити, що таке число об'єднання?
статичний

3
@statquant Я не запустив оригінальний показник, але дуже хотів би побачити, як Уес оновив тест.
Зак

Відповіді:


120

Схоже, Уес, можливо, виявив відому проблему, data.tableколи кількість унікальних рядків ( рівнів ) велика: 10 000.

Чи Rprof()виявляє більшу частину часу, проведеного у розмові sortedmatch(levels(i[[lc]]), levels(x[[rc]])? Це насправді не саме з'єднання (алгоритм), а попередній крок.

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

Чи зливаються панди швидше, ніж data.tableдля звичайних цілих стовпців? Це має бути способом ізоляції самого алгоритму від факторів.

Також на увазі data.tableє злиття часових рядів . Два аспекти цього: i) впорядковані клавіші з декількома стовпцями, такі як (id, datetime) ii) швидко переважаючі join ( roll=TRUE) aka останнє спостереження, перенесені вперед.

Мені знадобиться певний час, щоб підтвердити, оскільки це перше, що я бачив порівняння з 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 становить v1.8.10 на CRAN, і ми працюємо над v1.9.0. НОВИНИ оновлюються в прямому ефірі.


Але як я писав спочатку, вище:

data.tableмає на увазі злиття часових рядів . Два аспекти цього: i) впорядковані клавіші з декількома стовпцями, такі як (id, datetime) ii) швидко переважаючі join ( roll=TRUE) aka останнє спостереження, перенесені вперед.

Таким чином, з'єднання рівнянь Pandas з двох символьних стовпців, ймовірно, все ще швидше, ніж таблиця data.table. Оскільки це звучить, ніби хеширує поєднані дві колонки. data.table не має хеш-ключ, тому що в ньому переважають упорядковані з'єднання. "Ключ" у data.table - це буквально порядок сортування (аналогічно кластеризованому індексу в SQL; тобто, так впорядковані дані в оперативній пам'яті). До списку варто додати, наприклад, вторинні ключі.

Підводячи підсумок, яскрава різниця швидкостей, підкреслена цим тестом на два символи-стовпчики з понад 10 000 унікальних рядків, зараз не повинна бути такою поганою, оскільки відома проблема була виправлена.


6
Якщо ви надаєте тестовий випадок для досить великого, реалістичного набору даних, я буду радий запустити орієнтири. Ви також більше ніж ласкаво просимо. Насправді я ще не оптимізував код для цілого випадку ключових приєднань (поставте це у мій список todo!), Але ви можете очікувати значно кращої продуктивності, ніж строковий випадок, зважаючи на вивчення хеш-таблиці в пов'язаній презентації.
Уес Маккінні

22
Я не використовую жодної з цих бібліотек, але радий бачити конструктивну відповідь з боку R у формі Меттью Даула.
SlowLearner

3
Ось деякі результати Rprof pastie.org/3258362 . Схоже, 20-40% часу проводиться в сортованому збігу залежно від типу з'єднання. Доведеться шукати цілі стовпчики іншим разом - я створив панд GitHub, щоб нагадати мені оптимізувати цей випадок ( github.com/wesm/pandas/isissue/682 )
Уес МакКінні

14
@AndyHayden Покращення були зроблені деякий час тому. Я редагую в пунктах НОВИНИ. Уес вибрав на одному конкретному тесті (Equi, що поєднує дві колонки символів), який грав на цій відомій проблемі. Якби він вибрав цілі стовпці, було б інакше. І якби він дав мені голову перед тим, як презентувати показник на конференції, то я міг би розповісти йому більше про відому проблему.
Метт Даул

191

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

Порівняння з data.tableнасправді трохи цікаве, оскільки вся суть R data.tableполягає в тому, що він містить попередньо обчислені індекси для різних стовпців для прискорення операцій, таких як вибір даних і злиття. У цьому випадку (база даних приєднується) панди 'DataFrame не містить попередньо обчисленої інформації , яка використовується для злиття, так би мовити, це «холодне» злиття. Якби я зберігав факторизовані версії клавіш з'єднання, з'єднання було б значно швидше - оскільки факторизація є найбільшим вузьким місцем цього алгоритму.

Слід також додати, що внутрішній дизайн панд "DataFrame" набагато більше піддається цим операціям, ніж data.frame R (що є лише внутрішнім списком масивів).


76
Звичайно, тепер, коли ви все це зрозуміли в python, його слід легко перекласти на R;)
hadley

37
Але чому б хто-небудь хотів цього робити? :)
ely

9
Гм ... може тому, що вони хочуть, щоб операції з передачею даних були швидшими в R? Просто здогадуюсь :))
lebatsnok

28
Привіт Уес - здається, що ваші результати data.tableбули первинними за рахунок помилки, яку з тих пір виправлено. Будь-який шанс ви могли запустити свій показник і написати оновлену публікацію в блозі?
Зак

6
Zach переконайтеся, що ви це перевірили: github.com/Rdatatable/data.table/wiki/Benchmarks-:-Grouping
Merik

37

Цій темі вже два роки, але здається, що люди можуть скористатися можливим місцем приземлення під час пошуку порівнянь Панд і даних.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).


1
Я збирався опублікувати це! Дякуємо за додавання
Зак

7
@Zach дивіться це: github.com/szilard/benchm-databases, і це теж приємно: speakerdeck.com/szilard/…
jangorecki

1
@Zach через чотири роки з'явилися нові результати порівняння, дивіться мою відповідь нижче.
jangorecki

7

Є чудові відповіді, зокрема, зроблені авторами обох інструментів, про які задаються питання. Відповідь Метта пояснює випадок, про який повідомляється у запитанні, що це викликано помилкою, а не алгоритмом злиття. Помилка була виправлена ​​на наступний день, вже більше 7 років тому.

У своїй відповіді я надам декілька сучасних термінів операції злиття для data.table та pandas. Зверніть увагу, що злиття plyr та базового R не включені.

Часи, які я представляю, виходять із проекту db-бенчмарка , постійно відтворюваного відтворювального еталону. Він оновлює інструменти до останніх версій та запускає сценарії орієнтирів. У ньому працює багато інших програмних рішень. Якщо вас цікавлять Spark, Dask та кілька інших, обов'язково перевірте посилання.


На сьогодні… (ще належить реалізувати: ще один розмір даних та ще 5 питань)

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

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

Стіл RHS складається з 3 різних розмірів

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

У всіх випадках близько 90% збігаючих рядків між LHS та RHS, і жодних дублікатів у колоні приєднання RHS (немає декартового продукту).


Відтепер (запуск 2 листопада 2019 року)

Панди 0.25.3 випущені 1 листопада 2019 р.
data.table 0.12.7 (92abb70) опубліковано 2 листопада 2019 року

Нижче розраховані дані в секундах, для двох різних розмірів даних LHS. У стовпчик pd2dtдодається коефіцієнт зберігання поля, скільки разів панди повільніші, ніж дані.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 |
+-----------+--------------+----------+--------+
  • Дані LHS 5 Гб
+-----------+--------------+----------+--------+
| 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 |
+-----------+--------------+----------+--------+

Дякую за оновлення з майбутнього! Чи можете ви додати стовпчик для реалізації R vs python для реалізації data.table?
Зак

1
Я думаю, що добре просто зайти на веб-сайт і перевірити його, навіть не дивлячись на R dt vs pandas. І pyDT насправді не була частиною оригінального питання.
jangorecki
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.