【问题标题】:Outer merge on large pandas DataFrames causes MemoryError---how to do "big data" merges with pandas?大熊猫DataFrames的外部合并导致MemoryError---如何与熊猫进行“大数据”合并?
【发布时间】:2017-02-11 00:07:43
【问题描述】:

我有两个熊猫数据帧df1df2,格式相当标准:

   one  two  three   feature
A    1    2      3   feature1
B    4    5      6   feature2  
C    7    8      9   feature3   
D    10   11     12  feature4
E    13   14     15  feature5 
F    16   17     18  feature6 
...

df2 的格式相同。这些 DataFrame 的大小约为 175MB 和 140 MB。

merged_df = pd.merge(df1, df2, on='feature', how='outer', suffixes=('','_features'))

我得到以下内存错误:

File "/nfs/sw/python/python-3.5.1/lib/python3.5/site-packages/pandas/tools/merge.py", line 39, in merge
    return op.get_result()
File "/nfs/sw/python/python-3.5.1/lib/python3.5/site-packages/pandas/tools/merge.py", line 217, in get_result
    join_index, left_indexer, right_indexer = self._get_join_info()
File "/nfs/sw/python/python-3.5.1/lib/python3.5/site-packages/pandas/tools/merge.py", line 353, in _get_join_info
    sort=self.sort, how=self.how) 
File "/nfs/sw/python/python-3.5.1/lib/python3.5/site-packages/pandas/tools/merge.py", line 559, in _get_join_indexers
    return join_func(lkey, rkey, count, **kwargs)
File "pandas/src/join.pyx", line 187, in pandas.algos.full_outer_join (pandas/algos.c:61680)
  File "pandas/src/join.pyx", line 196, in pandas.algos._get_result_indexer (pandas/algos.c:61978)
MemoryError

合并时是否有可能对 pandas 数据框有“大小限制”?我很惊讶这行不通。也许这是某个版本的熊猫的一个错误?

编辑:如 cmets 中所述,合并列中的许多重复项很容易导致 RAM 问题。见:Python Pandas Merge Causing Memory Overflow

现在的问题是,我们如何进行这种合并?似乎最好的方法是以某种方式对数据框进行分区。

【问题讨论】:

  • 您的feature 列中有重复项吗?如果有很多重复项,您的联接最终可能会非常很大
  • @maxymoo 是的。你能解释一下为什么这会超过 RAM 限制吗?假设df1有1000万行,feature1有500K行,feature2有500K行等等。数据帧本身只有150 MB---为什么会出现内存错误?
  • 你用的是32位python/64位吗?
  • 如果 feature1 在 df1 中有 500K 行,在 df2 中有 500K 行,那么连接将有 500K*500K=250B 行
  • @SayaliSonawane 我现在明白了。不,这里没有 NaN 值 :)

标签: python pandas memory dataframe out-of-memory


【解决方案1】:

您可以尝试先过滤 df1 通过 unique 值、merge 和最后一个 concat 输出。

如果只需要外连接,我认为还有内存问题。但是如果为每个循环的过滤器输出添加一些其他代码,它就可以工作。

dfs = []
for val in df.feature.unique():
    df1 = pd.merge(df[df.feature==val], df2, on='feature', how='outer', suffixes=('','_key'))
    #http://stackoverflow.com/a/39786538/2901002
    #df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
    print (df1)
    dfs.append(df1)

df = pd.concat(dfs, ignore_index=True)
print (df)

其他解决方案是使用dask.dataframe.DataFrame.merge

【讨论】:

  • 我正在尝试合并(左连接)两个大数据帧,发生内存错误,请告诉我哪种方法适合@jezrael 合并而不会出现内存错误
【解决方案2】:

尝试为数字列指定数据类型以减小现有数据框的大小,例如:

df[['one','two', 'three']] = df[['one','two', 'three']].astype(np.int32)

这应该会显着减少内存,并有望让您执行合并。

【讨论】:

  • 我猜这对于非常大的连接可能没有太大帮助,如上所述。有没有一种有效的方法可以通过唯一的feature 拆分数据帧?如果(假设)100 MB 数据帧有 10 个特征,您可能会得到更小的数据帧(如果统一,每个大约 10 MB)
  • 我不确定按照您建议的方式拆分数据帧的有效方法,但可以删除两个初始数据帧之间共享的所有列。目标是外连接,因此删除不是数据帧唯一的列不会影响结果,但会减少内存。就像@jezrael 刚刚发布的答案一样。
猜你喜欢
  • 2020-10-26
  • 2020-05-04
  • 2018-04-21
  • 2013-09-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-02
  • 2018-07-05
相关资源
最近更新 更多