«Большие данные» рабочие потоки с использованием панд


983

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

Однажды я надеюсь заменить свое использование SAS на python и pandas, но в настоящее время мне не хватает неосновного рабочего процесса для больших наборов данных. Я говорю не о «больших данных», которые требуют распределенной сети, а о файлах, слишком больших, чтобы уместиться в памяти, но достаточно маленьких, чтобы уместиться на жестком диске.

Моя первая мысль - использовать HDFStoreдля хранения больших наборов данных на диске и извлекать только те части, которые мне нужны, в рамки данных для анализа. Другие упоминали MongoDB как более простую альтернативу. У меня вопрос такой:

Каковы лучшие рабочие процессы для достижения следующих целей:

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

Примеры из реальной жизни будут высоко оценены, особенно от тех, кто использует панд на «больших данных».

Редактировать - пример того, как я хотел бы, чтобы это работало:

  1. Итеративно импортируйте большой плоский файл и сохраните его в постоянной структуре базы данных на диске. Эти файлы обычно слишком велики, чтобы поместиться в памяти.
  2. Чтобы использовать Панд, я хотел бы прочитать подмножества этих данных (обычно всего несколько столбцов за раз), которые могут поместиться в памяти.
  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%? Имеет ли это значение - если бы вы могли сжать столбцы в int8 или отфильтровать шумные строки, это изменило бы ваш цикл вычисления-вычисления от, скажем, часов до минут? (Также добавьте тег big-data.)
Денис

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

Вы можете разделить свою задачу на куски работы?
Эндрю Скотт Эванс

1
Прекрасное решение 2019 года для выполнения панд, таких как операции со «средними» данными, которые не помещаются в памяти, - это dask
lunguini

Существуют альтернативы python + pandas, которые вы можете рассмотреть, когда только начинаете. Примите во внимание тот факт, что Python является языком программирования общего назначения (не DSL для сбора и анализа данных), и что pandas - это библиотека, к которой привязаны. Я хотел бы рассмотреть вопрос о R или KDB.
Генри Хенринсон

Ответы:


622

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

Стоит прочитать документы и в конце этой ветки несколько предложений о том, как хранить ваши данные.

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

  1. Размер данных, количество строк, столбцов, типы столбцов; Вы добавляете строки или просто столбцы?
  2. Как будут выглядеть типичные операции? Например, выполните запрос по столбцам, чтобы выбрать группу строк и определенных столбцов, затем выполните операцию (в памяти), создайте новые столбцы и сохраните их.
    (Приведя пример с игрушкой, мы можем предложить более конкретные рекомендации.)
  3. После этой обработки, что вы делаете? Шаг 2 является специальным или повторяемым?
  4. Входные плоские файлы: сколько, приблизительный общий размер в Гб. Как они организованы, например, по записям? Содержит ли каждый из них разные поля, или у них есть несколько записей на файл со всеми полями в каждом файле?
  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'])

Теперь у вас есть все таблицы в файле (на самом деле вы можете хранить их в отдельных файлах, если хотите, вам, вероятно, придется добавить имя файла в group_map, но, вероятно, в этом нет необходимости).

Вот как вы получаете столбцы и создаете новые:

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)

Когда вы будете готовы к post_processing:

# 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_columns, вам на самом деле не нужно определять ЛЮБЫЕ data_columns; они позволяют вам выбирать строки на основе столбца. Например, что-то вроде:

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

Они могут быть наиболее интересны для вас на последнем этапе создания отчета (по сути, столбец данных отделен от других столбцов, что может несколько повлиять на эффективность, если вы определите много).

Вы также можете захотеть:

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

Дайте мне знать, когда у вас есть вопросы!


5
Спасибо за ссылки. Вторая ссылка заставляет меня немного волноваться, что я не могу добавить новые столбцы к таблицам в HDFStore? Это верно? Также я добавил пример того, как я буду использовать эту настройку.
Zelazny7

4
Фактическая структура в hdf зависит от вас. Pytables ориентирован на строки с фиксированными столбцами во время создания. Вы не можете добавлять столбцы после создания таблицы. Однако вы можете создать новую таблицу, индексированную так же, как ваша существующая таблица. (см. примеры select_as_multiple в документации). Таким образом, вы можете создавать объекты произвольного размера, имея при этом довольно эффективные запросы. То, как вы используете данные, является ключом к тому, как они должны быть организованы на диске. Отправьте мне электронное письмо из списка рассылки с псевдокодом более конкретного примера.
Джефф

1
Я обновил свой вопрос, чтобы ответить на ваши подробные замечания. Я буду работать над примером, чтобы отправить вас из списка. Спасибо!
Zelazny7

12
@ Джефф, с Пандами, находящимися в 0.17.x, были ли проблемы, описанные выше, решены в Пандах?
Ctrl-Alt-Delete

5
@Джефф хочет добавить быстрое обновление вашего ответа, чтобы продвигать Dask?
Boud

137

Я думаю, что в ответах выше отсутствует простой подход, который я нашел очень полезным.

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

Пример: в случае торговых данных за 30 дней размером ~ 30 ГБ я разбиваю их на файл в день размером ~ 1 ГБ. Впоследствии я обрабатываю каждый файл отдельно и в конце собираю результаты

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

Другое преимущество состоит в том, что манипулирование файлами (например, добавление / удаление дат в примере) может быть выполнено с помощью обычных команд оболочки, что невозможно в более сложных / сложных форматах файлов.

Этот подход не охватывает все сценарии, но очень полезен во многих из них


39
Согласовано. При всей этой шумихе
zelusp

84

Теперь, спустя два года после вопроса, эквивалент панд "из ядра": dask . Это превосходно! Хотя он не поддерживает все функциональные возможности панд, вы можете продвинуться далеко вперед.


6
и для полностью проработанного примера с dask просто посмотрите здесь stackoverflow.com/questions/37979167/…
ℕʘʘḆḽḘ

В зависимости от ваших данных имеет смысл заглянуть в pystore . Это зависит от dask.
gies0r

66

Если ваши наборы данных имеют размер от 1 до 20 ГБ, вы должны получить рабочую станцию ​​с 48 ГБ ОЗУ. Тогда Pandas может хранить весь набор данных в оперативной памяти. Я знаю, что это не тот ответ, который вы ищете здесь, но делать научные вычисления на ноутбуке с 4 ГБ ОЗУ нецелесообразно.


7
«делать научные вычисления на ноутбуке с 4 ГБ ОЗУ нецелесообразно» Я думаю, что UNIVAC будет придерживаться другой точки зрения. arstechnica.com/tech-policy/2011/09/...
grisaitis

2
Согласовано! попытайтесь продолжить работу в памяти, даже если это стоит $$ авансом. Если ваша работа приводит к финансовой отдаче, то со временем вы окупите расходы за счет повышения эффективности.
17

2
Научные вычисления на рабочей станции с 48 ГБ ОЗУ нецелесообразны.
Ярослав Никитенко

4
@YaroslavNikitenko Увеличение r4.2 с 61 ГБ / RAM составляет $ 0,532 / час. Какие виды научных вычислений вы делаете, которые не так ценны? Звучит необычно, если не неразумно.
Рюрни

4
@rjurney извините, может быть, я должен был удалить свой комментарий. Ваше суждение о «необоснованном» научном компьютере кажется очень субъективным. Я много лет занимаюсь научными вычислениями на ноутбуках, и этого мне кажется достаточно, потому что большую часть времени я пишу код. Мои алгоритмы намного сложнее с точки зрения программирования, чем с вычислительной. Также я уверен, что при написании масштабируемых алгоритмов не следует полагаться на текущие аппаратные ограничения. Ваш комментарий по поводу вычислений других людей может показаться немного оскорбительным (кроме субъективности), не могли бы вы удалить эти несколько слов?
Ярослав Никитенко

59

Я знаю, что это старая ветка, но я думаю, что библиотеку Blaze стоит проверить. Он построен для подобных ситуаций.

Из документов:

Blaze расширяет возможности использования NumPy и Pandas для распределенных и неосновных вычислений. Blaze предоставляет интерфейс, похожий на интерфейс Num-Array NumPy или DataFrame Pandas, но отображает эти знакомые интерфейсы на множество других вычислительных движков, таких как Postgres или Spark.

Изменить: Кстати, это поддерживается ContinuumIO и Трэвис Олифант, автор NumPy.


GraphLab Create - еще одна библиотека, на которую стоит обратить внимание: она имеет эффективную структуру, подобную DataFrame, которая не ограничена объемом памяти. blog.dato.com/…
водонепроницаемый

52

Это дело для пимонго. Я также прототипировал с использованием SQL Server, SQLite, HDF, ORM (SQLAlchemy) в Python. Прежде всего, pymongo - это БД на основе документов, поэтому каждый человек будет документом ( dictс атрибутами). Многие люди формируют коллекцию, и вы можете иметь много коллекций (люди, фондовый рынок, доход).

pd.dateframe -> pymongo Примечание: я использую chunksizein 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поиск при создании документов.

Теперь у вас есть хороший набор данных, основанный на человеке, вы можете раскрыть свою логику в каждом случае и создать больше атрибутов. Наконец, вы можете прочитать в pandas ваши ключевые индикаторы 3 to max max и выполнить исследование pivots / agg / data. Это работает для меня 3 миллиона записей с числами / большой текст / категории / коды / плавающие / ...

Вы также можете использовать два метода, встроенных в MongoDB (MapReduce и агрегатный каркас). Смотрите здесь для получения дополнительной информации об агрегатной структуре , так как она кажется проще, чем MapReduce, и выглядит удобной для быстрой работы с агрегатами. Обратите внимание, что мне не нужно было определять мои поля или отношения, и я могу добавлять элементы в документ. В текущем состоянии быстро меняющегося набора инструментов numpy, pandas, python, MongoDB помогает мне просто приступить к работе :)


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

2
Да, я сделал то же самое для простого диапазона DF, и кажется, что int64 от numpy беспокоит pymongo. Все данные, с которыми я играл, конвертируются из CSV (искусственно через range ()) и имеют длинные типы и, следовательно, не имеют проблем. В NumPy вы можете конвертировать, но я считаю, что это отвлекает. Я должен признать, что 10,1 пунктов для HDF выглядят захватывающе.
brian_the_bungler

43

Я заметил это немного поздно, но я работаю с аналогичной проблемой (модели предоплаты ипотеки). Мое решение состояло в том, чтобы пропустить слой HDFStore pandas и использовать прямые таблицы. Я сохраняю каждый столбец как отдельный массив 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)

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

Обычно это работает для меня, но это немного неуклюже, и я не могу использовать причудливую магию pytables.

Изменить: реальное преимущество этого подхода, по сравнению с Pytables по умолчанию для массива записей, заключается в том, что я могу загрузить данные в R с помощью h5r, который не может обрабатывать таблицы. Или, по крайней мере, я не смог заставить его загружать разнородные таблицы.


Не могли бы вы поделиться со мной своим кодом? Меня интересует, как вы загружаете данные из какого-то простого текстового формата, не зная типов данных, прежде чем отправлять их в pytables. Кроме того, похоже, что вы работаете только с данными одного типа. Это верно?
Zelazny7

1
Прежде всего, я предполагаю, что знаю типы столбцов перед загрузкой, а не пытаюсь угадать по данным. Я сохраняю JSON-файл «data spec» с именами и типами столбцов и использую его при обработке данных. (Файл обычно представляет собой ужасный вывод BCP без каких-либо меток.) ​​Я использую типы данных: строки, числа с плавающей запятой, целые числа или месячные даты. Я превращаю строки в целочисленные значения, сохраняя таблицу перечислений и преобразуя даты в целые числа (месяцы после 2000 года), поэтому у меня остаются только целые числа и числа с плавающей точкой в ​​моих данных плюс перечисление. Теперь я сохраняю float как float64, но я экспериментировал с float32.
Иоганн Хибшман

1
если у вас есть время, пожалуйста , попробуйте это для внешнего сравнения с R: pandas.pydata.org/pandas-docs/dev/… , и если у вас возникнут трудности, возможно, мы сможем настроить его
Джефф

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

39

Один прием, который я нашел полезным для случаев использования больших данных, - это уменьшить объем данных за счет снижения точности с плавающей запятой до 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

27

Как отметили другие, через несколько лет появился « неосновательный» эквивалент панд: dask . Несмотря на то, что dask не является заменой панд и их функциональности, он выделяется по нескольким причинам:

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

Dask подчеркивает следующие достоинства:

  • Знакомый: Предоставляет распараллеленный массив NumPy и объекты Pandas DataFrame.
  • Гибкость: предоставляет интерфейс планирования задач для большего количества пользовательских рабочих нагрузок и интеграции с другими проектами.
  • Собственный: Включает распределенные вычисления в Pure Python с доступом к стеку PyData.
  • Быстро: работает с низкими издержками, низкой задержкой и минимальной сериализацией, необходимой для быстрых численных алгоритмов
  • Масштабируется: гибко работает на кластерах с тысячами ядер. Масштабируется: тривиально настроить и запустить на ноутбуке за один процесс
  • Отзывчивый: разработанный с учетом интерактивных вычислений, он обеспечивает быструю обратную связь и диагностику, чтобы помочь людям

и добавить простой пример кода:

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

Еще один вариант

Многие из операций, выполняемых в пандах, также могут выполняться в виде запросов к базе данных (sql, mongo).

Использование СУБД или 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)

9

Я хотел бы указать на пакет Vaex.

Vaex - это библиотека Python для ленивых внешних фреймов данных (похожих на Pandas) для визуализации и изучения больших табличных наборов данных. Он может рассчитывать статистику, такую ​​как среднее, сумма, число, стандартное отклонение и т. Д., В N-мерной сетке до миллиарда (10 9 ) объектов / строк в секунду. Визуализация выполняется с использованием гистограмм, графиков плотности и трехмерного рендеринга, что позволяет интерактивно исследовать большие данные. Vaex использует отображение памяти, политику нулевого копирования памяти и ленивые вычисления для лучшей производительности (без потери памяти).

Посмотрите документацию: https://vaex.readthedocs.io/en/latest/ API очень близок к API панд.


0

Почему панды? Вы пробовали стандартный Python ?

Использование стандартной библиотеки Python. Pandas подвержен частым обновлениям, даже с недавним выпуском стабильной версии.

Используя стандартную библиотеку python, ваш код всегда будет работать.

Один из способов сделать это - иметь представление о том, как вы хотите, чтобы ваши данные хранились, и какие вопросы вы хотите решить относительно данных. Затем нарисуйте схему того, как вы можете организовать свои данные (таблицы), которые помогут вам запрашивать данные, не обязательно нормализации.

Вы можете эффективно использовать:

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

Ram и HDD становятся все дешевле и дешевле, а стандартный Python 3 широко доступен и стабилен.


-1

В данный момент я работаю «как вы», просто по более низкой шкале, поэтому у меня нет PoC для моего предложения.

Тем не менее, я, кажется, добился успеха в использовании pickle в качестве системы кеширования и аутсорсинга выполнения различных функций в файлы - выполнение этих файлов из моего файла commando / main; Например, я использую prepare_use.py для преобразования типов объектов, разделения набора данных на набор данных тестирования, проверки и прогнозирования.

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

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

Я надеюсь, что мои 2 цента помогут вам в некотором роде.

Приветствую.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.