【问题标题】:Pandas Dataframe too large for memory, problems implementing daskPandas Dataframe 对内存来说太大,实现 dask 的问题
【发布时间】:2018-11-17 07:19:23
【问题描述】:

我正在编写一个脚本,它将我的模拟数据添加到一个 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

【问题讨论】:

    标签: python pandas dataframe dask


    【解决方案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 构建 pandas 数据帧。

    【讨论】:

      【解决方案2】:

      请将其作为带有一些代码的注释而不是答案。 我不确定您所做的是否是与熊猫合作的最佳方式。当您想存储结果时,最好将它们保存为块。然后当你想做一些分析时,你可以用 dask 阅读它们。 我将尝试以它们的结果适合内存的方式拆分模拟并将它们保存到磁盘。假设只有 100 个模拟适合内存,你可以为每 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 并行运行这个块(这主要取决于模拟。它是单线程的还是不是单线程的?)

      【讨论】:

        猜你喜欢
        • 2017-06-08
        • 2018-10-07
        • 1970-01-01
        • 2010-12-24
        • 2023-03-07
        • 2020-11-26
        • 1970-01-01
        • 1970-01-01
        • 2018-05-06
        相关资源
        最近更新 更多