我有三个要连接的 DataFrame。
concat_df = pd.concat([df1, df2, df3])
这会导致 MemoryError。我该如何解决这个问题?
请注意,大多数现有的类似问题都是关于读取大文件时发生的 MemoryErrors。我没有那个问题。我已将我的文件读入 DataFrames 中。我只是无法连接这些数据。
原文由 bluprince13 发布,翻译遵循 CC BY-SA 4.0 许可协议
我有三个要连接的 DataFrame。
concat_df = pd.concat([df1, df2, df3])
这会导致 MemoryError。我该如何解决这个问题?
请注意,大多数现有的类似问题都是关于读取大文件时发生的 MemoryErrors。我没有那个问题。我已将我的文件读入 DataFrames 中。我只是无法连接这些数据。
原文由 bluprince13 发布,翻译遵循 CC BY-SA 4.0 许可协议
就像在其他答案中看到的那样,问题是记忆问题。一个解决方案是将数据存储在磁盘上,然后构建一个唯一的数据框。
对于如此庞大的数据,性能是一个问题。
csv 解决方案非常慢,因为在文本模式下会发生转换。自从使用二进制模式以来,HDF5 解决方案更短、更优雅、更快。我提出了二进制模式的第三种方式,使用 pickle ,它似乎更快,但更具技术性并且需要更多空间。第四个,手工。
这里的代码:
import numpy as np
import pandas as pd
import os
import pickle
# a DataFrame factory:
dfs=[]
for i in range(10):
dfs.append(pd.DataFrame(np.empty((10**5,4)),columns=range(4)))
# a csv solution
def bycsv(dfs):
md,hd='w',True
for df in dfs:
df.to_csv('df_all.csv',mode=md,header=hd,index=None)
md,hd='a',False
#del dfs
df_all=pd.read_csv('df_all.csv',index_col=None)
os.remove('df_all.csv')
return df_all
更好的解决方案:
def byHDF(dfs):
store=pd.HDFStore('df_all.h5')
for df in dfs:
store.append('df',df,data_columns=list('0123'))
#del dfs
df=store.select('df')
store.close()
os.remove('df_all.h5')
return df
def bypickle(dfs):
c=[]
with open('df_all.pkl','ab') as f:
for df in dfs:
pickle.dump(df,f)
c.append(len(df))
#del dfs
with open('df_all.pkl','rb') as f:
df_all=pickle.load(f)
offset=len(df_all)
df_all=df_all.append(pd.DataFrame(np.empty(sum(c[1:])*4).reshape(-1,4)))
for size in c[1:]:
df=pickle.load(f)
df_all.iloc[offset:offset+size]=df.values
offset+=size
os.remove('df_all.pkl')
return df_all
对于同构数据帧,我们可以做得更好:
def byhand(dfs):
mtot=0
with open('df_all.bin','wb') as f:
for df in dfs:
m,n =df.shape
mtot += m
f.write(df.values.tobytes())
typ=df.values.dtype
#del dfs
with open('df_all.bin','rb') as f:
buffer=f.read()
data=np.frombuffer(buffer,dtype=typ).reshape(mtot,n)
df_all=pd.DataFrame(data=data,columns=list(range(n)))
os.remove('df_all.bin')
return df_all
以及对(小,32 Mb)数据进行一些测试以比较性能。对于 4 Gb,您必须乘以大约 128。
In [92]: %time w=bycsv(dfs)
Wall time: 8.06 s
In [93]: %time x=byHDF(dfs)
Wall time: 547 ms
In [94]: %time v=bypickle(dfs)
Wall time: 219 ms
In [95]: %time y=byhand(dfs)
Wall time: 109 ms
一张支票:
In [195]: (x.values==w.values).all()
Out[195]: True
In [196]: (x.values==v.values).all()
Out[196]: True
In [197]: (x.values==y.values).all()
Out[196]: True
当然,所有这些都必须改进和调整以适应您的问题。
例如,df3 可以分成大小为“total_memory_size - df_total_size”的块,以便能够运行 bypickle
。
如果您愿意的话,如果您提供有关数据结构和大小的更多信息,我可以对其进行编辑。美丽的问题!
原文由 B. M. 发布,翻译遵循 CC BY-SA 4.0 许可协议
2 回答5.1k 阅读✓ 已解决
2 回答1.1k 阅读✓ 已解决
4 回答1k 阅读✓ 已解决
3 回答1.1k 阅读✓ 已解决
3 回答1.2k 阅读✓ 已解决
1 回答1.7k 阅读✓ 已解决
1 回答1.2k 阅读✓ 已解决
我很感谢社区的回答。但是,就我而言,我发现问题实际上是由于我使用的是 32 位 Python。
Windows 32 和 64 位操作系统定义了 内存限制。对于 32 位 进程,它只有 2 GB。所以,即使你的 RAM 超过 2GB,即使你运行的是 64 位操作系统,但你运行的是 32 位进程,那么该进程将仅限于 2GB 的 RAM - 在我的例子中是进程是蟒蛇。
我升级到 64 位 Python,从那以后就没有内存错误了!
其他相关问题是: 64 位窗口上的 Python 32 位内存限制, 我应该使用 Python 32 位还是 Python 64 位, 为什么这个 numpy 数组太大而无法加载?