pandas 变量赋值后出现内存不足错误
pandas out of memory error after variable assignment
我有一个非常大的 pandas 数据框,想从中采样行进行建模,我遇到了这样的内存不足错误:
MemoryError: Unable to allocate 6.59 GiB for an array with shape (40, 22117797) and data type float64
这个错误很奇怪,因为我不需要分配这么大的内存,因为我的采样数据帧只有原始数据的 1%。下面是我的代码。
具体来说,原始数据有2000万行,大部分是np.float64数据。使用 pyarrow 从 parquet 文件加载数据后,jupyter 内核占用大约 3 GB 内存。使用“d0['r_%s'%(t)] = d0.col0”变量赋值后,内核占用 6 GB。但是,一旦我 运行 采样命令“d0s = d0.iloc[id1,:]”,内存就会上升到 13 GB,程序会由于上面的内存不足错误而停止。
下面的代码是使用 pandas 1.2.3.
在 16GB 内存机器上重现错误的最小工作示例
import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 12))
for t in range(30):
d0['r_%s'%(t)] = d0[0]
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
请注意,如果我直接生成一个大数据帧,以下代码不会产生错误:
import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 42))
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
我发现错误是由于执行了合并操作 pandas。具体来说,在使用“d0['r_%s'%(t)] = d0[0]”进行变量赋值后,d0存储在13个块中,即:13个连续内存space,可以检查使用命令
d0._data.nblocks
一旦我 运行 命令“d0s = d0.iloc[id1,:]”, pandas 试图将 13 个块合并为 1 个块,所以这个新版本 d0 与1 块将占用很多内存 space,我的内存用完了。所以弹出内存不足的错误。可以使用较小的数组检查单块合并,如下所示:
import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 12))
for t in range(10):
d0['r_%s'%(t)] = d0[0]
d0._data.nblocks
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
d0._data.nblocks
为了解决这个问题,我使用了另一种方式来获取值而不触发合并操作,如下所示:
d0s = pd.concat([d0.iloc[id1,col] for col in d0.columns], axis = 1)
希望这对遇到类似问题的其他人有所帮助。
我有一个非常大的 pandas 数据框,想从中采样行进行建模,我遇到了这样的内存不足错误:
MemoryError: Unable to allocate 6.59 GiB for an array with shape (40, 22117797) and data type float64
这个错误很奇怪,因为我不需要分配这么大的内存,因为我的采样数据帧只有原始数据的 1%。下面是我的代码。
具体来说,原始数据有2000万行,大部分是np.float64数据。使用 pyarrow 从 parquet 文件加载数据后,jupyter 内核占用大约 3 GB 内存。使用“d0['r_%s'%(t)] = d0.col0”变量赋值后,内核占用 6 GB。但是,一旦我 运行 采样命令“d0s = d0.iloc[id1,:]”,内存就会上升到 13 GB,程序会由于上面的内存不足错误而停止。
下面的代码是使用 pandas 1.2.3.
在 16GB 内存机器上重现错误的最小工作示例import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 12))
for t in range(30):
d0['r_%s'%(t)] = d0[0]
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
请注意,如果我直接生成一个大数据帧,以下代码不会产生错误:
import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 42))
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
我发现错误是由于执行了合并操作 pandas。具体来说,在使用“d0['r_%s'%(t)] = d0[0]”进行变量赋值后,d0存储在13个块中,即:13个连续内存space,可以检查使用命令
d0._data.nblocks
一旦我 运行 命令“d0s = d0.iloc[id1,:]”, pandas 试图将 13 个块合并为 1 个块,所以这个新版本 d0 与1 块将占用很多内存 space,我的内存用完了。所以弹出内存不足的错误。可以使用较小的数组检查单块合并,如下所示:
import pandas as pd
import numpy as np
d0 = pd.DataFrame(np.random.rand(22117797, 12))
for t in range(10):
d0['r_%s'%(t)] = d0[0]
d0._data.nblocks
id1 = np.random.randint(low = 0, high = d0.shape[0], size = round(d0.shape[0]*0.01))
d0s = d0.iloc[id1,:]
d0._data.nblocks
为了解决这个问题,我使用了另一种方式来获取值而不触发合并操作,如下所示:
d0s = pd.concat([d0.iloc[id1,col] for col in d0.columns], axis = 1)
希望这对遇到类似问题的其他人有所帮助。