Pandas Dataframe对于内存来说太大了,实现了dask的问题

时间:2018-06-07 11:33:14

标签: python pandas dataframe dask

我正在编写一个脚本,将我的模拟数据添加到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并为每个模拟值保存它。但这似乎效率低下,我想我应该能够在dask中做到这一点。

有什么建议吗?

我正在操作Windows,20 GB RAM,SSD,i7如果有帮助

2 个答案:

答案 0 :(得分:1)

正如错误消息所示,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来构造熊猫数据框。

答案 1 :(得分:0)

请将其作为评论与某些代码而不是答案。 我不确定你做的是否是与熊猫一起工作的最佳方式。由于您希望存储结果,因此将它们保存为块可能会更好。然后当你想做一些分析时,你可以用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')

最后,您可以与daskmultiprocessing并行运行此块(它主要取决于模拟。它是否是单线程的?)