DataFrame Pandas слишком велик для памяти, проблемы с реализацией dask - PullRequest
0 голосов
/ 07 июня 2018

Я пишу скрипт, который добавляет мои смоделированные данные в фрейм данных pandas для n имитаций в моем цикле.Когда я выбираю значение n> ~ 15, он падает, я думаю, что моя df становится слишком большой для хранения в памяти во время выполнения моих симуляций.

Я создаю пустой DF

df = pd.DataFrame(
    {'gamma': [],
     'alpha': [],
     'focus': [],
     'X' : [],
     'Y' : [],
     'Z' : [],
     'XX' : [],
     'img1' : [],
     'img2' : [],
     'num_samples' : [],
     'resolution' : []})

for i in range(n):
#some simulation stuffs 

, а затем заполняю свой фрейм данных значениями

df.loc[i] = (
    {'gamma': gamma,
    'alpha': alpha,
    'focus': focus,
    'X' : X,
    'Y' : Y,
    'Z' : Z,
    'XX' : XX,
    'img1' : img1,
    'img2' : img2,
    'num_samples' : num_samples,
    'resolution' : resolution})

Я пробегаю это n раз, чтобы заполнить свой df, а затемсохрани это.Однако это продолжает терпеть крах.Я подумал, что dask.dataframe может быть хорошим здесь:

df = dd.from_pandas(pd.DataFrame(
{'gamma': [],
 'alpha': [],
 'focus': [],
 'X' : [],
 'Y' : [],
 'Z' : [],
 'XX' : [],
 'img1' : [],
 'img2' : [],
 'num_samples' : [],
 'resolution' : []
}), chunksize=10)

и затем заполнить мои данные

df.loc[i] = {'probe': wave.array.real,
    'gamma': gamma,
    'alpha': alpha,
    'focus': focus,
    'X' : X,
    'Y' : Y,
    'Z' : Z,
    'XX' : X,
    'img1' : img1,
    'img2' : img2,
    'num_samples' : num_samples,
    'resolution' : resolution}

Но я получаю ошибку '_LocIndexer' object does not support item assignment

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

Любые предложения?

Я работаю Windows, 20 ГБ ОЗУ, SSD, i7, если это помогает

Ответы [ 2 ]

0 голосов
/ 07 июня 2018

Как следует из сообщения об ошибке, Dask, как правило, не позволяет вам изменять содержимое кадра данных на месте.Кроме того, действительно необычно пытаться добавить или иным образом изменить размер кадра данных dask после его создания.Поскольку у вас не хватает памяти, Dask по-прежнему является вашим предпочтительным инструментом, так что вот что может быть самым простым способом сделать это, оставаясь близко к исходному коду.

meta = pd.DataFrame(
    {'gamma': [],
     'alpha': [],
     'focus': [],
     'X' : [],
     'Y' : [],
     'Z' : [],
     'XX' : [],
     'img1' : [],
     'img2' : [],
     'num_samples' : [],
     'resolution' : []})

def chunk_to_data(df):
    out = meta.copy()
    for i in df.i:
        out.loc[i] = {...}
    return out

# the pandas dataframe will be small enough to fit in memory
d = dd.from_pandas(pd.DataFrame({'i': range(n)}, chunksize=10)

d.map_partitions(chunk_to_data, meta=meta)

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

В общем, возможно, было бы лучше использовать dask.delayed с функцией, принимающей start-i и end-i, чтобы создать кадры данных для каждого куска без входного кадра данных, а затем dd.from_delayed, чтобы построить кадр данных pandas.

0 голосов
/ 07 июня 2018

Пожалуйста, примите это как комментарий с некоторым кодом, а не как ответ.Я не уверен, что то, что вы делаете, - лучший способ работать с пандами.Поскольку вы хотите сохранить результаты, возможно, лучше сохранить их как чанк.Затем, когда вы захотите провести некоторый анализ, вы можете прочитать их с помощью dask.Я постараюсь разделить симуляции таким образом, чтобы их результаты помещались в память и сохраняли их на диск.Пусть говорит, что в память помещается только 100 симуляций, которые вы можете сделать для каждого фрагмента 100

import pandas as pd

cols = ['gamma', 'alpha', 'focus', 'X',
        'Y', 'Z', 'XX', 'img1', 'img2',
        'num_samples', 'resolution']

mem = 100
out = []
for i in range(mem):
    # simulation returns list results
    out.append(results)

df = pd.DataFrame(out, columns=cols)
df.to_csv('results/filename01.csv')
# or even better 
df.to_parquet('results/filename01.parq')

Наконец, вы можете запустить этот блок параллельно с dask или multiprocessing (это в основном зависит от симуляции.Это однопоточный или нет?)

...