将数据帧腌制到磁盘时出现内存错误

Bak*_*war 5 python numpy pandas

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

我写了以下代码:

将数据pickle到磁盘

outfile=open("df_preference.p", "wb")
pickle.dump(df_preference,outfile)
outfile.close()
Run Code Online (Sandbox Code Playgroud)

它向我抛出内存错误,如下所示:

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()
Run Code Online (Sandbox Code Playgroud)

我假设这意味着这些数据很大并且无法腌制?但它只有二进制值。

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

df_preference=df_recommender.applymap(lambda x: np.where(x >0, 1, 0))
Run Code Online (Sandbox Code Playgroud)

创建 df_preference 本身就花费了一些时间。矩阵大小相同。

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

谢谢

Max*_*axU 4

更新:

\n\n

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

\n\n
(df_recommender > 0).astype(np.int8).to_pickle(\'/path/to/file.pickle\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
In [1]: df = pd.DataFrame(np.random.randint(0, 10, size=(51000, 9000)))\n\nIn [2]: df.shape\nOut[2]: (51000, 9000)\n\nIn [3]: df.info()\n<class \'pandas.core.frame.DataFrame\'>\nRangeIndex: 51000 entries, 0 to 50999\nColumns: 9000 entries, 0 to 8999\ndtypes: int32(9000)\nmemory usage: 1.7 GB\n
Run Code Online (Sandbox Code Playgroud)\n\n

源 DF 需要 1.7 GB 内存

\n\n
In [6]: df_preference = (df>0).astype(int)\n\nIn [7]: df_preference.info()\n<class \'pandas.core.frame.DataFrame\'>\nRangeIndex: 51000 entries, 0 to 50999\nColumns: 9000 entries, 0 to 8999\ndtypes: int32(9000)\nmemory usage: 1.7 GB\n
Run Code Online (Sandbox Code Playgroud)\n\n

生成的 DF 再次需要 1.7 GB 内存

\n\n
In [4]: df_preference = (df>0).astype(np.int8)\n\nIn [5]: df_preference.info()\n<class \'pandas.core.frame.DataFrame\'>\nRangeIndex: 51000 entries, 0 to 50999\nColumns: 9000 entries, 0 to 8999\ndtypes: int8(9000)\nmemory usage: 437.7 MB\n
Run Code Online (Sandbox Code Playgroud)\n\n

使用int8dtype 只需 438 MB

\n\n

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

\n\n
In [10]: df_preference.to_pickle(\'d:/temp/df_pref.pickle\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

文件大小:

\n\n
{ temp }  \xc2\xbb ls -lh df_pref.pickle\n-rw-r--r-- 1 Max None 438M May 28 09:20 df_pref.pickle\n
Run Code Online (Sandbox Code Playgroud)\n\n

旧答案:

\n\n

试试这个:

\n\n
(df_recommender > 0).astype(int).to_pickle(\'/path/to/file.pickle\')\n
Run Code Online (Sandbox Code Playgroud)\n\n

说明:

\n\n
In [200]: df\nOut[200]:\n   a  b  c\n0  4  3  3\n1  1  2  1\n2  2  1  0\n3  2  0  1\n4  2  0  4\n\nIn [201]: (df>0).astype(int)\nOut[201]:\n   a  b  c\n0  1  1  1\n1  1  1  1\n2  1  1  0\n3  1  0  1\n4  1  0  1\n
Run Code Online (Sandbox Code Playgroud)\n\n

PS,您可能还想将 DF 保存为 HDF5 文件而不是 Pickle -有关详细信息,请参阅此比较

\n