关于python:内存错误,同时将数据框腌制到磁盘

Memory Error while pickling a data frame to disk

我有一个51K X 8.5K数据帧,只有二进制(1或0)值。

我写了以下代码:

将数据腌制到磁盘上

1
2
3
outfile=open("df_preference.p","wb")
pickle.dump(df_preference,outfile)
outfile.close()

它抛出了我的内存错误如下:

1
2
3
4
5
6
MemoryError                               Traceback (most recent call last)
<ipython-input-48-de66e880aacb> in <module>()
      2
      3 outfile=open("df_preference.p","wb")
----> 4 pickle.dump(df_preference,outfile)
      5 outfile.close()

我假设它意味着这个数据很大而且不能被腌制? 但它只有二进制值。

在此之前,我从另一个具有正常计数和大量零的数据框架创建了此数据集。 使用以下代码:

1
df_preference=df_recommender.applymap(lambda x: np.where(x >0, 1, 0))

这本身需要一些时间来创建df_preference。 相同尺寸的矩阵。

我担心的是,如果使用applymap创建数据框需要时间,而ii)由于内存错误甚至没有腌制数据帧,那么我需要使用SVD和交替最小二乘法对此df_prefence进行矩阵分解。 那会更慢吗? 如何解决这个慢速运行并解决内存错误?

谢谢


更新:

对于10值,您可以使用int8(1字节)dtype,这将使您的内存使用量减少至少4倍。

1
(df_recommender > 0).astype(np.int8).to_pickle('/path/to/file.pickle')

以下是51K x 9K数据帧的示例:

1
2
3
4
5
6
7
8
9
10
11
In [1]: df = pd.DataFrame(np.random.randint(0, 10, size=(51000, 9000)))

In [2]: df.shape
Out[2]: (51000, 9000)

In [3]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 51000 entries, 0 to 50999
Columns: 9000 entries, 0 to 8999
dtypes: int32(9000)
memory usage: 1.7 GB

源DF需要1.7 GB的内存

1
2
3
4
5
6
7
8
In [6]: df_preference = (df>0).astype(int)

In [7]: df_preference.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 51000 entries, 0 to 50999
Columns: 9000 entries, 0 to 8999
dtypes: int32(9000)
memory usage: 1.7 GB

结果DF再次需要1.7 GB的内存

1
2
3
4
5
6
7
8
In [4]: df_preference = (df>0).astype(np.int8)

In [5]: df_preference.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 51000 entries, 0 to 50999
Columns: 9000 entries, 0 to 8999
dtypes: int8(9000)
memory usage: 437.7 MB

使用int8 dtype只需438 MB

现在让我们将它保存为Pickle文件:

1
In [10]: df_preference.to_pickle('d:/temp/df_pref.pickle')

文件大小:

1
2
{ temp }  ? ls -lh df_pref.pickle
-rw-r--r-- 1 Max None 438M May 28 09:20 df_pref.pickle

老答案:

试试这个:

1
(df_recommender > 0).astype(int).to_pickle('/path/to/file.pickle')

Explanataion:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
In [200]: df
Out[200]:
   a  b  c
0  4  3  3
1  1  2  1
2  2  1  0
3  2  0  1
4  2  0  4

In [201]: (df>0).astype(int)
Out[201]:
   a  b  c
0  1  1  1
1  1  1  1
2  1  1  0
3  1  0  1
4  1  0  1

PS你可能还想将你的DF保存为HDF5文件而不是Pickle - 请参阅此比较以获取详细信息