Робочі потоки "великих даних" використовуються за допомогою панд


980

Я багато років намагався розгадати відповідь на це питання, вивчаючи панди. Я використовую SAS для своєї повсякденної роботи, і це чудово, оскільки вона є позапрофільною підтримкою. Однак SAS є жахливим як частина програмного забезпечення з багатьох інших причин.

Одного разу я сподіваюся замінити своє використання SAS на python і pandas, але в даний час мені не вистачає непрофільного робочого процесу для великих наборів даних. Я не говорю про "великі дані", які вимагають розподіленої мережі, а про файли, занадто великі, щоб вміститись у пам'яті, але досить малі, щоб вмістити на жорсткому диску.

Перша моя думка - використовувати HDFStoreдля зберігання великих наборів даних на диску і тягнути лише ті шматочки, які мені потрібні, в рамки даних для аналізу. Інші згадували MongoDB як простішу у використанні альтернативу. Моє запитання таке:

Назвіть кілька кращих практичних процесів для досягнення наступного:

  1. Завантаження плоских файлів у постійну структуру бази даних на диску
  2. Запит на цю базу даних для отримання даних для подачі в структуру даних панди
  3. Оновлення бази даних після маніпулювання фрагментами в пандах

Приклади реального світу були б дуже вдячні, особливо від усіх, хто використовує панди на "великі дані".

Редагувати - приклад того, як я хотів би, щоб це працювало:

  1. Ітераційно імпортуйте великий плоский файл і зберігайте його в постійній структурі бази даних на диску. Ці файли, як правило, занадто великі, щоб вміститись у пам'яті.
  2. Для того, щоб використовувати Pandas, я хотів би прочитати підмножини цих даних (як правило, лише кілька стовпців одночасно), які можуть вміститися в пам'яті.
  3. Я б створив нові стовпці, виконуючи різні операції над вибраними стовпцями.
  4. Тоді я повинен був би додати ці нові стовпці до структури бази даних.

Я намагаюся знайти найкращий спосіб виконання цих кроків. Читаючи посилання про панди та піблети, здається, що додавання нового стовпця може бути проблемою.

Редагувати - Відповідаючи конкретно на запитання Джеффа:

  1. Я будую моделі споживчого кредитного ризику. Види даних включають характеристики телефону, SSN та адреси; значення властивостей; зневажлива інформація, така як судимість, банкрутства тощо ... Набори даних, які я використовую щодня, мають у середньому від 1000 до 2000 полів змішаних типів даних: безперервні, номінальні та порядкові змінні як числових, так і символьних даних. Я рідко додаю рядки, але я виконую багато операцій, які створюють нові стовпці.
  2. Типові операції передбачають об'єднання декількох стовпців за допомогою умовної логіки в новий, складений стовпець. Наприклад, if var1 > 2 then newvar = 'A' elif var2 = 4 then newvar = 'B'. Результатом цих операцій є новий стовпець для кожного запису в моєму наборі даних.
  3. Нарешті, я хотів би додати ці нові стовпці до структури даних на диску. Я б повторив крок 2, досліджуючи дані за допомогою перехресних таблиць та описової статистики, намагаючись знайти цікаві, інтуїтивні зв’язки для моделювання.
  4. Типовий файл проекту зазвичай становить близько 1 ГБ. Файли організовані таким чином, коли ряд складається з запису даних про споживачів. Кожен рядок має однакову кількість стовпців для кожного запису. Це завжди буде так.
  5. Досить рідко я підміняв би рядки під час створення нового стовпця. Однак для мене досить часто зустрічається підмножина в рядках під час створення звітів або генерування описової статистики. Наприклад, я можу захотіти створити просту частоту для конкретної сфери бізнесу, скажімо, кредитні картки роздрібної торгівлі. Для цього я б вибрав лише ті записи, де напрямок бізнесу = роздрібна торгівля, окрім тих колонок, про які я хочу повідомити. Однак при створенні нових стовпців я б витягував усі рядки даних і лише стовпці, які мені потрібні для операцій.
  6. Процес моделювання вимагає, щоб я проаналізував кожний стовпець, шукав цікаві зв’язки з деякою змінною результатів і створював нові складні стовпці, які описують ці відносини. Колонки, які я досліджую, зазвичай робляться невеликими наборами. Наприклад, я зупинюся на наборі скажімо 20 стовпців, що стосуються лише цінностей майна, і спостерігатиму, як вони стосуються дефолту за кредитом. Після того, як вони будуть вивчені та створені нові стовпці, я перейду до іншої групи стовпців, скажімо про освіту в коледжі, і повторюю процес. Що я роблю, це створення змінних кандидатів, які пояснюють взаємозв'язок між моїми даними та певним результатом. В кінці цього процесу я застосовую деякі методи навчання, які створюють рівняння з цих складених стовпців.

Рідко коли-небудь я додав би рядки до набору даних. Я майже завжди буду створювати нові стовпці (змінні чи функції в статистиці / машинному навчанні).


1
Чи співвідношення розміру серцевини / повного розміру 1%, 10%? Чи не має значення - якби ви могли стиснути cols до int8 або відфільтрувати галасливі рядки, чи змінить це цикл обчислень-думок з годин на хвилини? (Також додайте тег великих даних.)
деніс

1
Зберігання float32 замість float64 та int8, де це можливо, має бути тривіальним (не знаю, які інструменти / функції виконують float64 всередині)
denis

ви можете розділити своє завдання на шматки роботи?
Ендрю Скотт Еванс

1
приємне рішення 2019 року робити панди на зразок операцій над "середніми" даними, які не вміщуються в пам'яті, - даск
lunguini

Є альтернативи пантонам python +, які ви можете розглянути як побачити, як тільки починаєте. Розглянемо той факт, що Python - це мова програмування загального призначення (а не DSL для обробки даних та аналізу даних) і що панди - це бібліотека, на яку зверху позначено. Я б розглядав R або kdb.
Генрі Генрінсон

Відповіді:


621

Я звичайно використовую десятки гігабайт даних саме таким чином, наприклад, у мене на диску є таблиці, які я читаю за допомогою запитів, створюю дані та додаю назад.

Варто ознайомитися з документами та пізно в цій темі, щоб отримати кілька пропозицій щодо збереження даних.

Деталі, які впливатимуть на збереження ваших даних, наприклад:
Наведіть якомога більше деталей; і я можу допомогти вам розробити структуру.

  1. Розмір даних, кількість рядків, стовпців, типи стовпців; Ви додаєте рядки чи просто стовпці?
  2. Як виглядатимуть типові операції. Наприклад, зробіть запит на стовпчики, щоб вибрати купу рядків і конкретних стовпців, потім зробіть операцію (в пам'яті), створіть нові стовпці, збережіть ці.
    (Наведення прикладу іграшки може дати нам можливість запропонувати більш конкретні рекомендації.)
  3. Після цієї обробки, що ви робите? Чи є етап 2 тимчасовим чи повторюваним?
  4. Введіть плоскі файли: скільки, приблизний загальний розмір у Gb. Як вони організовані, наприклад, записами? Чи міститься кожне з різних полів, чи є у них деякі записи на файл із усіма полями у кожному файлі?
  5. Ви коли-небудь вибираєте підмножини рядків (записів) на основі критеріїв (наприклад, вибираєте рядки з полем A> 5)? а потім щось робити або просто вибираєте поля A, B, C із усіма записами (а потім щось робите)?
  6. Ви працюєте над усіма своїми стовпцями (у групах), чи є хороша частка, яку ви можете використовувати лише для звітів (наприклад, ви хочете зберігати дані навколо, але не потрібно втягувати в них чіткість стовпців, поки підсумковий час)?

Рішення

Переконайтеся, що у вас встановлені принаймні панди0.10.1 .

Прочитайте ітераційні файли, накреслені по черзі та кілька запитів таблиці .

Оскільки pytables оптимізовані для роботи в строкових строках (про що ви і запитуєте), ми створимо таблицю для кожної групи полів. Таким чином легко вибрати невелику групу полів (які будуть працювати з великою таблицею, але ефективніше це зробити так ... Я думаю, що я можу в майбутньому виправити це обмеження ... це інтуїтивніше все одно):
(Далі йде псевдокод.)

import numpy as np
import pandas as pd

# create a store
store = pd.HDFStore('mystore.h5')

# this is the key to your storage:
#    this maps your fields to a specific group, and defines 
#    what you want to have as data_columns.
#    you might want to create a nice class wrapping this
#    (as you will want to have this map and its inversion)  
group_map = dict(
    A = dict(fields = ['field_1','field_2',.....], dc = ['field_1',....,'field_5']),
    B = dict(fields = ['field_10',......        ], dc = ['field_10']),
    .....
    REPORTING_ONLY = dict(fields = ['field_1000','field_1001',...], dc = []),

)

group_map_inverted = dict()
for g, v in group_map.items():
    group_map_inverted.update(dict([ (f,g) for f in v['fields'] ]))

Читання файлів та створення сховища (по суті, що append_to_multipleробить)

for f in files:
   # read in the file, additional options may be necessary here
   # the chunksize is not strictly necessary, you may be able to slurp each 
   # file into memory in which case just eliminate this part of the loop 
   # (you can also change chunksize if necessary)
   for chunk in pd.read_table(f, chunksize=50000):
       # we are going to append to each table by group
       # we are not going to create indexes at this time
       # but we *ARE* going to create (some) data_columns

       # figure out the field groupings
       for g, v in group_map.items():
             # create the frame for this group
             frame = chunk.reindex(columns = v['fields'], copy = False)    

             # append it
             store.append(g, frame, index=False, data_columns = v['dc'])

Тепер у вас є всі таблиці у файлі (насправді ви можете зберігати їх в окремих файлах, якщо хочете, вам потрібно буде додати ім'я файлу до групи_мапа, але, ймовірно, це не потрібно).

Ось як ви отримуєте стовпці та створюєте нові:

frame = store.select(group_that_I_want)
# you can optionally specify:
# columns = a list of the columns IN THAT GROUP (if you wanted to
#     select only say 3 out of the 20 columns in this sub-table)
# and a where clause if you want a subset of the rows

# do calculations on this frame
new_frame = cool_function_on_frame(frame)

# to 'add columns', create a new group (you probably want to
# limit the columns in this new_group to be only NEW ones
# (e.g. so you don't overlap from the other tables)
# add this info to the group_map
store.append(new_group, new_frame.reindex(columns = new_columns_created, copy = False), data_columns = new_columns_created)

Коли ви будете готові до пост_обробки:

# This may be a bit tricky; and depends what you are actually doing.
# I may need to modify this function to be a bit more general:
report_data = store.select_as_multiple([groups_1,groups_2,.....], where =['field_1>0', 'field_1000=foo'], selector = group_1)

Щодо колонок data_column, вам насправді не потрібно визначати БУДЬ-які стовпці даних; вони дозволяють підбирати рядки на основі стовпця. Наприклад, щось на зразок:

store.select(group, where = ['field_1000=foo', 'field_1001>0'])

Вони можуть бути вам найбільш цікавими на етапі формування остаточного звіту (по суті, стовпець даних відокремлений від інших стовпців, що може дещо вплинути на ефективність, якщо ви визначите багато).

Ви також можете:

  • створити функцію, яка займає список полів, шукає групи в groups_map, потім вибирає їх і об'єднує результати, щоб ви отримали отриманий кадр (це, по суті, те, що робить select_as_multiple). Таким чином структура буде для вас досить прозорою.
  • індексує для певних стовпців даних (робить підмножини рядків набагато швидшими).
  • включити стиснення.

Дайте мені знати, коли у вас є питання!


5
Дякуємо за посилання. Друге посилання мене трохи хвилює, що я не можу додавати нові стовпці до таблиць у HDFStore? Це правильно? Крім того, я додав приклад того, як я буду використовувати цю установку.
Zelazny7

4
Фактична структура у форматі hdf залежить від вас. Піблети орієнтовані на рядки з фіксованими стовпцями на час створення. Не можна додавати стовпці, коли створено таблицю. Однак ви можете створити нову таблицю з індексом так само, як і існуючу таблицю. (див. приклади select_as_multiple в документах). Таким чином ви можете створювати об'єкти довільного розміру, маючи досить ефективні запити. Спосіб використання даних є ключовим для того, як вони мають бути організовані на диску. Надішліть мені електронну пошту поза списком із псевдокодом більш конкретного прикладу.
Джефф

1
Я оновив своє запитання, щоб відповісти на ваші детальні моменти. Я буду працювати над прикладом, щоб відправити вас поза списком. Дякую!
Zelazny7

12
@Jeff, коли Pandas знаходиться на рівні 0,17.x, чи вирішені вищезазначені проблеми в Pandas?
ctrl-alt-delete

5
@Jeff зацікавлений у додаванні швидкого оновлення вашої відповіді, щоб рекламувати даск?
Буд

137

Я думаю, що у відповідях вище не вистачає простого підходу, який я вважаю дуже корисним.

Коли у мене занадто великий файл, щоб завантажити його в пам'ять, я розбиваю його на кілька менших файлів (або на рядки, або на значки)

Приклад: Якщо дані про торги вартістю 30 днів розміром ~ 30 ГБ, я розбиваю їх на файл розміром ~ 1 ГБ. Згодом я обробляю кожен файл окремо та збираю результати в кінці

Однією з найбільших переваг є те, що вона дозволяє паралельну обробку файлів (або декількох потоків, або процесів)

Інша перевага полягає в тому, що маніпулювання файлами (наприклад, додавання / видалення дат у прикладі) може здійснюватися звичайними командними оболонками, що неможливо у більш просунутих / складних форматах файлів

Цей підхід охоплює не всі сценарії, але дуже корисний у багатьох з них


39
Домовились. З усією галасливістю
zelusp

83

Зараз, через два роки після запитання, " позапрофільний " еквівалент панди: даск . Це чудово! Хоча він не підтримує всі функціональні можливості панд, ви можете отримати дуже далеко з ним.


6
і повністю розробленої , наприклад , з DASK, просто подивіться тут stackoverflow.com/questions/37979167 / ...
ℕʘʘḆḽḘ

Залежно від ваших даних є сенс заглянути в пістор . Це спирається на dask.
gies0r

66

Якщо ваші набори даних становлять від 1 до 20 Гб, вам слід отримати робочу станцію з 48 ГБ оперативної пам’яті. Тоді Pandas може вмістити весь набір даних в оперативній пам'яті. Я знаю, що це не відповідь, яку ви шукаєте тут, але робити наукові обчислення на ноутбуці з 4 Гб оперативної пам’яті нерозумно.


7
"Робити наукові обчислення на ноутбуці з 4 ГБ оперативної пам'яті не є розумним" Визначте розумне. Я думаю, що UNIVAC би по-іншому. arstechnica.com/tech-policy/2011/09/…
грисаїт

2
Домовились! спробуйте продовжувати працювати в пам'яті, навіть якщо це коштує $$ наперед. Якщо ваша робота призводить до фінансової віддачі, то з часом ви компенсуєте витрати завдяки підвищенню ефективності.
ansonw

2
Робити наукові обчислення на робочій станції з 48 Гб оперативної пам’яті нерозумно.
Ярослав Нікітенко

4
@YaroslavNikitenko Рівень 2,2 з більшою швидкістю 61 ГБ / ОЗУ становить $. Якими ви науковими обчисленнями займаєтесь, що не так цінно? Звучить незвично, якщо не безпідставно.
rjurney

4
@rjurney Вибачте, можливо, я мав би видалити свій коментар. Ваше судження про "необґрунтований" науковий комп'ютер видається дуже суб'єктивним. Я роблю свої наукові обчислення роками на ноутбуках, і мені це здається достатньо, тому що більшість часу я пишу код. Мої алгоритми набагато складніше з точки зору програмування, ніж з обчислювальної. Також я впевнений, що для написання масштабованих алгоритмів не слід покладатися на поточні обмеження на обладнання. Ваш коментар до обчислень інших людей може здатися трохи образливим (окрім суб'єктивності), чи не проти ви видалити ці кілька слів?
Ярослав Нікітенко

58

Я знаю, що це стара тема, але я думаю, що бібліотеку Blaze варто перевірити. Він побудований для таких типів ситуацій.

З документів:

Blaze розширює зручність використання NumPy та Pandas на розподілені та поза основні обчислення. Blaze пропонує інтерфейс, подібний до NumPy ND-Array або Pandas DataFrame, але відображає ці звичні інтерфейси на безліч інших обчислювальних двигунів, таких як Postgres або Spark.

Редагувати: До речі, його підтримують ContinuumIO та Travis Oliphant, автор NumPy.


Ще одна бібліотека, на яку варто звернути увагу - це GraphLab Create: Вона має ефективну структуру, схожу на DataFrame, яка не обмежена ємністю пам'яті. blog.dato.com/…
водонепроникний

52

Це стосується пімонго. Я також прототипував, використовуючи sql-сервер, sqlite, HDF, ORM (SQLAlchemy) у python. Перш за все, pymongo - це БД на основі документа, тому кожна людина буде документом ( dictатрибутами). Багато людей формують колекцію, і ви можете мати багато колекцій (люди, фондовий ринок, дохід).

pd.dateframe -> PyMongo Примітка: Я використовую chunksizeв read_csvтримати його 5 до 10k записів (PyMongo падає гніздо , якщо більше)

aCollection.insert((a[1].to_dict() for a in df.iterrows()))

запит: gt = більше, ніж ...

pd.DataFrame(list(mongoCollection.find({'anAttribute':{'$gt':2887000, '$lt':2889000}})))

.find()повертає ітератор, тому я зазвичай використовую ichunkedдля подрібнення менших ітераторів.

Як щодо об’єднання, оскільки я зазвичай отримую 10 джерел даних, які потрібно вставити разом:

aJoinDF = pandas.DataFrame(list(mongoCollection.find({'anAttribute':{'$in':Att_Keys}})))

потім (у моєму випадку іноді мені доводиться aJoinDFспочатку нарікатись перед її "злиттям".)

df = pandas.merge(df, aJoinDF, on=aKey, how='left')

Потім ви можете записати нову інформацію у свою основну колекцію за допомогою наведеного нижче способу оновлення. (логічний збір проти фізичних джерел даних).

collection.update({primarykey:foo},{key:change})

На менших оглядах просто денормалізуйте. Наприклад, у вас є документ у документі, і ви просто додаєте текст кодового поля та здійснюєте dictпошук під час створення документів.

Тепер у вас є гарний набір даних на основі людини, ви можете розкрити свою логіку в кожному конкретному випадку і зробити більше атрибутів. Нарешті, ви можете прочитати в пандах ваші 3-ма максимальні індикатори пам'яті та зробити обертові / agg / дані. Це працює для мене на 3 мільйони записів з цифрами / великий текст / категорії / коди / поплавці / ...

Ви також можете використовувати два методи, вбудовані в MongoDB (MapReduce та агрегатний фреймворк). Дивіться тут для отримання додаткової інформації про агрегатний каркас , оскільки це здається простіше, ніж MapReduce, і виглядає зручно для швидкої роботи в агрегаті. Зверніть увагу, що мені не потрібно було визначати свої поля чи відносини, і я можу додати елементи до документа. У поточному стані швидко змінюються нуме, панди, набору інструментів python MongoDB допомагає мені просто приступити до роботи :)


Привіт, я граю з вашим прикладом , а також і я біжу в цю помилку при спробі вставити в базу даних: In [96]: test.insert((a[1].to_dict() for a in df.iterrows())) --------------- InvalidDocument: Cannot encode object: 0. Будь-які ідеї, що може бути неправильним? Мій кадр даних складається з усіх типів int64 і дуже простий.
Zelazny7

2
Так, я зробив те ж саме для простого діапазону DF, а int64 від numpy, здається, турбує Pymongo. Усі дані, з якими я грав, перетворюються з CSV (проти штучно через range ()) і мають типи довгі, а отже, жодних проблем. У numpy ви можете конвертувати, але я вважаю, що це призводить до шкоди. Треба визнати, що 10,1 пункту для HDF виглядають захоплююче.
brian_the_bungler

43

Я помітив це трохи пізно, але працюю з подібною проблемою (моделі передплати за іпотекою). Моїм рішенням було пропустити шар HDFStore панди та використовувати прямі піблети. Я зберігаю кожен стовпець як окремий масив HDF5 у своєму остаточному файлі.

Моя основна робота - це спочатку отримати файл CSV з бази даних. Я gzip це, так що це не так величезно. Потім я конвертую його у файл, орієнтований на рядки HDF5, шляхом ітерації над ним у python, перетворення кожного рядка у реальний тип даних та записування його у файл HDF5. Це займає кілька десятків хвилин, але вона не використовує жодної пам’яті, оскільки вона працює лише рядком за рядком. Потім я "транспоную" файл, орієнтований на рядки HDF5, у файл HDF5, орієнтований на стовпчик.

Транспонування таблиці виглядає так:

def transpose_table(h_in, table_path, h_out, group_name="data", group_path="/"):
    # Get a reference to the input data.
    tb = h_in.getNode(table_path)
    # Create the output group to hold the columns.
    grp = h_out.createGroup(group_path, group_name, filters=tables.Filters(complevel=1))
    for col_name in tb.colnames:
        logger.debug("Processing %s", col_name)
        # Get the data.
        col_data = tb.col(col_name)
        # Create the output array.
        arr = h_out.createCArray(grp,
                                 col_name,
                                 tables.Atom.from_dtype(col_data.dtype),
                                 col_data.shape)
        # Store the data.
        arr[:] = col_data
    h_out.flush()

Читання його тоді виглядає так:

def read_hdf5(hdf5_path, group_path="/data", columns=None):
    """Read a transposed data set from a HDF5 file."""
    if isinstance(hdf5_path, tables.file.File):
        hf = hdf5_path
    else:
        hf = tables.openFile(hdf5_path)

    grp = hf.getNode(group_path)
    if columns is None:
        data = [(child.name, child[:]) for child in grp]
    else:
        data = [(child.name, child[:]) for child in grp if child.name in columns]

    # Convert any float32 columns to float64 for processing.
    for i in range(len(data)):
        name, vec = data[i]
        if vec.dtype == np.float32:
            data[i] = (name, vec.astype(np.float64))

    if not isinstance(hdf5_path, tables.file.File):
        hf.close()
    return pd.DataFrame.from_items(data)

Зараз я, як правило, запускаю це на машині з тоною пам’яті, тому я, можливо, не насторожуюсь із використанням моєї пам’яті. Наприклад, за замовчуванням операція завантаження зчитує весь набір даних.

Це, як правило, працює для мене, але це трохи незграбно, і я не можу використовувати магію фантазійних піблеток.

Редагувати: Справжня перевага цього підходу над типовим для масиву записів пітограмами за замовчуванням полягає в тому, що я можу потім завантажувати дані в R за допомогою h5r, який не може обробляти таблиці. Або, принаймні, я не зміг змусити його завантажувати неоднорідні таблиці.


Ви б не хотіли поділитися зі мною частиною свого коду? Мене цікавить, як ви завантажуєте дані з якогось плоского текстового формату, не знаючи типів даних, перш ніж натискати на піблети. Крім того, схоже, ви працюєте лише з даними одного типу. Це правильно?
Zelazny7

1
Перш за все, я припускаю, що знаю типи стовпців перед завантаженням, а не намагаюся вгадати з даних. Я зберігаю JSON файл "специфікація даних" із назвами та типами стовпців і використовую його під час обробки даних. (Файл, як правило, жахливий вихід BCP без міток.) ​​Типи даних, які я використовую, це рядки, поплавці, цілі числа або місячні дати. Я перетворюю рядки в int, зберігаючи таблицю перерахування і конвертую дати в ints (місяці минулого 2000 року), тому мені просто залишилися в моїх даних ints та floats, а також перерахування. Я зберігаю floats як float64 зараз, але я експериментував з float32.
Йоганн Хібшман

1
Якщо у вас є час, будь ласка, спробуйте це зробити для зовнішнього співпраці з R: pandas.pydata.org/pandas-docs/dev/… , і якщо у вас виникнуть труднощі, можливо, ми можемо підправити це
Jeff

Я спробую, якщо зможу. rhdf5 - це біль, оскільки це біокондукторний пакет, а не просто на CRAN, як h5r. Я в силі нашої команди з технічної архітектури, і в останній раз, коли я про це звернувся, виникла проблема з rhdf5. У будь-якому випадку, здається, помилка переходити на рядки, а не на стовпчики з магазином OLAP, але зараз я розбираюся.
Йоганн Хібшман

38

Один фокус, який я знайшов корисним для великих випадків використання даних, - це зменшити об'єм даних за рахунок зменшення точності поплавця до 32-розрядних. Це застосовується не у всіх випадках, але у багатьох додатках 64-бітова точність є надмірною, а економія пам’яті в 2 рази варта того. Щоб зробити очевидний момент ще більш очевидним:

>>> df = pd.DataFrame(np.random.randn(int(1e8), 5))
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float64(5)
memory usage: 3.7 GB

>>> df.astype(np.float32).info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 100000000 entries, 0 to 99999999
Data columns (total 5 columns):
...
dtypes: float32(5)
memory usage: 1.9 GB

26

Як зазначають інші, через кілька років з'явився " непростий " еквівалент панди: даск . Хоча даск не є заміною панди і вся її функціональність виділяється з кількох причин:

Dask - це гнучка бібліотека паралельних обчислень для аналітичних обчислень, яка оптимізована для динамічного планування завдань для інтерактивних обчислювальних навантажень колекцій «Big Data», таких як паралельні масиви, фрейми даних та списки, що розширюють загальні інтерфейси, такі як ітератори NumPy, Pandas або Python, на більші, ніж пам'ять або розподілене середовище та масштаби від ноутбуків до кластерів.

Даск наголошує на наступних чеснотах:

  • Знайоме: надає паралелізований масив NumPy та об'єкти Pandas DataFrame
  • Гнучка: надає інтерфейс планування завдань для більшої кількості користувацьких навантажень та інтеграції з іншими проектами.
  • Native: Дозволяє розподіляти обчислення на Pure Python з доступом до стеку PyData.
  • Швидкий: працює з низькими накладними витратами, низькою затримкою та мінімальною серіалізацією, необхідною для швидких числових алгоритмів
  • Масштаби вгору: Еластично працює на кластерах з 1000-ти ядрами Масштаби вниз: Тривіальне налаштування та запуск на ноутбуці за один процес
  • Чуйний: Розроблений з урахуванням інтерактивних обчислень, він забезпечує швидкий зворотний зв'язок та діагностику для допомоги людям

і додати простий зразок коду:

import dask.dataframe as dd
df = dd.read_csv('2015-*-*.csv')
df.groupby(df.user_id).value.mean().compute()

замінює такий код панди, як цей:

import pandas as pd
df = pd.read_csv('2015-01-01.csv')
df.groupby(df.user_id).value.mean()

і, особливо примітно, забезпечує через concurrent.futuresінтерфейс загальну інфраструктуру для подання користувацьких завдань:

from dask.distributed import Client
client = Client('scheduler:port')

futures = []
for fn in filenames:
    future = client.submit(load, fn)
    futures.append(future)

summary = client.submit(summarize, futures)
summary.result()

Я додав цю відповідь, оскільки публікація @Private регулярно відображається у запропонованому для видалення списку щодо вмісту та тривалості.
wp78de

17

Варто згадати тут і Рея ,
це розподілена обчислювальна рамка, яка має власну реалізацію для панд розподіленим способом.

Просто замініть імпорт панд, і код повинен працювати так:

# import pandas as pd
import ray.dataframe as pd

#use pd as usual

Ви можете прочитати більше деталей тут:

https://rise.cs.berkeley.edu/blog/pandas-on-ray/


16

Ще одна варіація

Багато операцій, виконаних у пандах, також можна виконати як db-запит (sql, mongo)

Використання RDBMS або mongodb дозволяє виконувати деякі агрегації в БД-запиті (який оптимізовано для великих даних і ефективно використовує кеш і індекси)

Пізніше ви можете виконати обробку пошти, використовуючи панди.

Перевага цього методу полягає в тому, що ви отримуєте оптимізацію БД для роботи з великими даними, одночасно визначаючи логіку в декларативному синтаксисі високого рівня - і не потрібно мати справу з деталями вирішення, що робити в пам'яті і що робити основної.

І хоча мова запитів і панди різні, перекладати частину логіки з однієї на іншу зазвичай не складно.


11

Подумайте про Ruffus, якщо ви підете простим шляхом створення конвеєра даних, який розбивається на кілька менших файлів.


9

Нещодавно я натрапив на подібне питання. Я виявив, що просто читати дані в кусках і додавати їх, коли я записую їх у шматки до того ж csv, добре працює. Моєю проблемою було додавання стовпця дати на основі інформації в іншій таблиці, використовуючи значення певних стовпців наступним чином. Це може допомогти тим, хто плутається dask та hdf5, але більше знайомий з пандами, як я.

def addDateColumn():
"""Adds time to the daily rainfall data. Reads the csv as chunks of 100k 
   rows at a time and outputs them, appending as needed, to a single csv. 
   Uses the column of the raster names to get the date.
"""
    df = pd.read_csv(pathlist[1]+"CHIRPS_tanz.csv", iterator=True, 
                     chunksize=100000) #read csv file as 100k chunks

    '''Do some stuff'''

    count = 1 #for indexing item in time list 
    for chunk in df: #for each 100k rows
        newtime = [] #empty list to append repeating times for different rows
        toiterate = chunk[chunk.columns[2]] #ID of raster nums to base time
        while count <= toiterate.max():
            for i in toiterate: 
                if i ==count:
                    newtime.append(newyears[count])
            count+=1
        print "Finished", str(chunknum), "chunks"
        chunk["time"] = newtime #create new column in dataframe based on time
        outname = "CHIRPS_tanz_time2.csv"
        #append each output to same csv, using no header
        chunk.to_csv(pathlist[2]+outname, mode='a', header=None, index=None)

8

Я хотів би зазначити пакет Vaex.

Vaex - бібліотека пітонів для ледачих поза-основних DataFrames (подібно до Pandas) для візуалізації та дослідження великих табличних наборів даних. Він може обчислювати статистику, таку як середнє значення, сума, підрахунок, стандартне відхилення тощо на N-мірній сітці до мільярда (10 9 ) об'єктів / рядків в секунду. Візуалізація проводиться за допомогою гістограм, графіків щільності та 3D-рендерингу обсягу, що дозволяє інтерактивне дослідження великих даних. Vaex використовує відображення пам'яті, нульову політику копіювання пам'яті та ледачі обчислення для найкращої продуктивності (не витрачається пам'ять).

Погляньте на документацію: https://vaex.readthedocs.io/en/latest/ API дуже близький до API панд.


0

Чому панди? Ви пробували Standard Python ?

Використання стандартного бібліотечного пітона. Панди підлягають частому оновленню навіть при нещодавньому випуску стабільної версії.

Використовуючи стандартну бібліотеку python, ваш код завжди працюватиме.

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

Ви можете добре скористатися:

  • список словників для зберігання даних у пам'яті, один дикт - один рядок,
  • генератори для обробки даних за рядком, щоб не переповнювати оперативну пам’ять,
  • перелічити розуміння для запиту ваших даних,
  • використовувати Counter, DefaultDict, ...
  • зберігайте свої дані на жорсткому диску, використовуючи яке б рішення для зберігання ви обрали, json може бути одним із них.

Ram і HDD з часом стає дешевше і дешевше, а стандартний python 3 широко доступний і стабільний.


-1

На даний момент я працюю "як" ти, лише нижчою шкалою, тому я не маю PoC для своєї пропозиції.

Однак, здається, я знаходжу успіх у використанні маринованої системи в якості системи кешування та аутсорсингу виконання різних функцій у файлах - виконання цих файлів із мого командного / головного файлу; Наприклад, я використовую Prepa_use.py для перетворення типів об'єктів, розділення набору даних на тест, перевірку та набір даних прогнозування.

Як працює кешування з солінням? Я використовую рядки, щоб отримати доступ до файлів pickle, які динамічно створюються, залежно від того, які параметри та набори даних передані (за допомогою цього я намагаюсь захопити та визначити, чи програма вже запущена, використовуючи .shape для набору даних, dict для переданих параметри). Поважаючи ці заходи, я отримую рядок, щоб спробувати знайти і прочитати .pickle-файл, і, якщо його знайдуться, можна пропустити час обробки, щоб перейти до виконання, над яким я зараз працюю.

Використовуючи бази даних, я зіткнувся з подібними проблемами, тому я знайшов радість від використання цього рішення, однак - напевно є багато обмежень - наприклад, зберігання величезних наборів соління через надмірність. Оновлення таблиці від раніше до трансформації можна здійснити за допомогою належної індексації - перевірка інформації відкриває цілу іншу книгу (я спробував консолідувати скановані дані оренди і перестала використовувати базу даних через 2 години, як я хотів би відскочити після кожен процес трансформації)

Я сподіваюся, що мої 2 копійки в чомусь допоможуть вам.

Привітання.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.