从SciPy稀疏矩阵中填充Pandas SparseDataFrame

36
我注意到Pandas现在支持稀疏矩阵和数组。目前,我创建DataFrame()的方式如下:
return DataFrame(matrix.toarray(), columns=features, index=observations)

有没有一种方法可以使用 scipy.sparse.csc_matrix()csr_matrix() 创建一个 SparseDataFrame()?转换为密集格式会严重消耗内存。谢谢!

1
现在有一个实验性的API:http://pandas-docs.github.io/pandas-docs-travis/sparse.html#interaction-with-scipy-sparse - K3---rnc
3个回答

30

目前不支持直接转换。欢迎贡献!

可以尝试这个方法,因为SpareSeries很像csc_matrix(只有1列),所以在内存方面应该没问题,而且空间利用率也相当高。

In [37]: col = np.array([0,0,1,2,2,2])

In [38]: data = np.array([1,2,3,4,5,6],dtype='float64')

In [39]: m = csc_matrix( (data,(row,col)), shape=(3,3) )

In [40]: m
Out[40]: 
<3x3 sparse matrix of type '<type 'numpy.float64'>'
        with 6 stored elements in Compressed Sparse Column format>

In [46]: pd.SparseDataFrame([ pd.SparseSeries(m[i].toarray().ravel()) 
                              for i in np.arange(m.shape[0]) ])
Out[46]: 
   0  1  2
0  1  0  4
1  0  0  5
2  2  3  6

In [47]: df = pd.SparseDataFrame([ pd.SparseSeries(m[i].toarray().ravel()) 
                                   for i in np.arange(m.shape[0]) ])

In [48]: type(df)
Out[48]: pandas.sparse.frame.SparseDataFrame

太棒了,谢谢!我只是在这里随口一想,但既然SciPy稀疏格式实际上只是一个数据数组和两个索引数组,我们是否可以通过这种方式来填充SparseDataFrame呢? - Will
4
(在当前的实现中)最好按系列(列)填充数据;这样可以基本上创建一个内部索引(称为 int 索引)或块索引(类似于 bsr/csr),以便定位数值。您考虑进行哪些操作? - Jeff
这对于CSR矩阵来说是否有所不同,还是推荐的方式? - Sid
1
Jeff,使用这种方法在我的情况下并不能节省内存,调用 df.memory_usage().sum() 的结果与我只是这样创建数据框的结果相同:pd.DataFrame(mtx.todense())。但是,如果我在此处添加 to_sparse 方法 pd.DataFrame(mtx.todense()).to_sparse(fill_value=0) 并再次调用 df.memory_usage().sum(),结果会更少。也许这很容易回答,但我有点卡住了。 - Timothy Dalton
1
不太确定你在做什么,这是一个相当旧的版本。请尝试使用更新的pandas,如果还是不行,请开一个issue或者在Stack Overflow上提问。 - Jeff
值得注意的是,您代码中的矩阵类型为csc,从中获取行的速度较慢。将整个矩阵转换为CSR格式或使用getcol(i)获取列而不是行方法会更快。如果您获取所需的列,则需要考虑在df中获取转置矩阵。 - eSadr

20

从pandas v0.20.0开始,您可以使用SparseDataFrame构造函数。

以下是来自Pandas文档的一个示例:

import numpy as np
import pandas as pd
from scipy.sparse import csr_matrix

arr = np.random.random(size=(1000, 5))
arr[arr < .9] = 0
sp_arr = csr_matrix(arr)
sdf = pd.SparseDataFrame(sp_arr)

-8
一个更短的版本:
df = pd.DataFrame(m.toarray())

10
不幸的是,toarray() 将稀疏矩阵转换为密集矩阵,并使用大量的内存。 - Will
1
这是简短简单的代码,对于我相对较小的数据集来说,内存消耗是可以接受的折衷方案。 - DaReal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接