【问题标题】:No space benefit using sparse Pandas dataframe despite extremely low density尽管密度极低,但使用稀疏 Pandas 数据帧没有空间优势
【发布时间】:2026-01-25 05:15:02
【问题描述】:

我正在使用 Python/Pandas 处理非常大且非常稀疏的单列数据帧,但是当我腌制它们时,几乎没有任何好处。如果我在 Matlab 上尝试同样的事情,差异是巨大的,所以我试图了解发生了什么。

使用熊猫:

len(SecondBins)
>> 34300801

dense = pd.DataFrame(np.zeros(len(SecondBins)),columns=['Binary'],index=SecondBins)
sparse = pd.DataFrame(np.zeros(len(SecondBins)),columns=['Binary'],index=SecondBins).to_sparse(fill_value=0)

pickle.dump(dense,open('dense.p','wb'))
pickle.dump(sparse,open('sparse.p','wb'))

查看腌制文件的大小, 密集 = 548.8MB 稀疏 = 274.4MB

但是,当我查看与这些变量相关的内存使用情况时,

dense.memory_usage()
>>Binary    274406408
>>dtype: int64

sparse.memory_usage()
>>Binary    0
>>dtype: int64

因此,对于一个完全空的稀疏向量,可以节省 50% 以上。也许这与变量“SecondBins”由我在 Pandas 中用作索引的 pd.Timestamp 组成这一事实有关,因此我尝试使用默认索引进行类似的过程。

dense_defaultindex = pd.DataFrame(np.zeros(len(SecondBins)),columns=['Binary'])
sparse_defaultindex = pd.DataFrame(np.zeros(len(SecondBins)),columns=['Binary']).to_sparse(fill_value=0)

pickle.dump(dense_defaultindex,open('dense_defaultindex.p','wb'))
pickle.dump(sparse_defaultindex,open('sparse_defaultindex.p','wb'))

但它在磁盘上产生相同的大小。

pickle 在后台做什么? 如果我在 Matlab 中创建一个类似的零填充向量,并将其保存在 .mat 文件中,它大约是 180 字节!?

请指教。

问候

【问题讨论】:

  • 我不确定这里发生了什么,但是您是否熟悉所有 pandas 存储选项(包括 pickle 对象的方法,这可能等同于您在这里所做的)? pandas.pydata.org/pandas-docs/stable/io.html 特别是您可能需要考虑 to_hdf,这是一种存储 pandas 数据帧并支持压缩的常用方法。
  • 您好,感谢您的建议。我尝试过使用 .to_hdf 函数,但没有得到任何明显的改进。例如,>>>SecondsDataFrame.to_hdf('sparse.hdf',key='thing',format='fixed',mode='w',complevel=9) 也产生约 274MB。我想我只是将向量以 scipy.sparse 格式存储在磁盘上,如果我需要在 Pandas 中访问一个进行操作,我可以即时生成标签。我想这并不理想,但我有数千个,所以以密集格式存储它们真的不是一种选择......如果你有更好的想法,我会全力以赴。谢谢:)
  • 对,b/c 你存储的索引不是稀疏的,正如@TheBlackCat 解释得很好。如果您有多个列,则优势会更大,因为索引只需要存储一次,在这种情况下,您会看到更大的比例节省。这完全取决于您的数据是什么样的以及您正在使用它做什么......

标签: python pandas pickle sparse-matrix


【解决方案1】:

请记住,pandas 是 标记 数据。列标签和索引标签本质上是专门的数组,这些数组占用空间。因此,在实践中,就空间使用而言,索引充当附加列,列标题充当附加行。

在密集的情况下,您基本上有两列,即数据和索引。在稀疏情况下,您基本上只有一列,即索引(因为备用数据列几乎不包含数据)。所以从这个角度来看,你会期望稀疏情况大约是密集情况的一半。这就是您在文件大小中看到的内容。

然而,在 MATLAB 的情况下,数据没有被标记。因此,稀疏情况几乎不占用空间。与 MATLAB 案例等效的是稀疏矩阵,而不是备用数据帧结构。因此,如果您想充分利用节省的空间,您应该使用scipy.sparse,它提供的稀疏矩阵支持类似于您在 MATLAB 中获得的支持。

【讨论】:

  • 您好,感谢您的全面回复。我已经尝试过 scipy.sparse 库,正如你所说: >>> from scipy.sparse import csc_matrix >>> sparse = csc_matrix((34300801,1), dtype=np.float) >>> pickle.dump(sparse ,open('sparse_cscmatrix.p','wb')) 腌制保存文件的大小约为 400 字节!我想我会将它用于我所有的向量,并且只保存一次标签,分别。我了解 Pandas 是标记数据;但是,这就是为什么我还使用标准索引(从 0-len(array) 开始)对其进行了测试,但我想它还不够聪明......
  • 熊猫不会聪明。它总是使用标签。即使您不创建它们,它们仍然存在。如果您不想使用标签,请不要使用熊猫。话虽如此,如果您要创建许多具有相同索引的行矩阵,则可以将它们用作单个数据帧的列,而不是为每个数据帧创建一个单独的数据帧。我认为这比在其他地方保留单独的索引更简单。