我正在寻找一种更好的方法来从scipy sparse matrix创建pandas dataframe。
这是我目前拥有的伪代码
row = []; column = []; values = []
for each row of the dataframe
for each column of the row
add the row_id to row
add the column_id to column
add the value to values
sparse_matrix = sparse.coo_matrix((values, (row, column), shape=(max(row)+1,max(column)+1))
但我个人认为会有更好的办法。几乎起作用的是以下
dataframe.unstack().to_sparse().to_coo()
然而,这给了我三倍的(稀疏矩阵,列id和行id)。问题是我需要行id实际上是稀疏矩阵的一部分。
这是一个完整的例子。我有一个如下所示的数据框
instructor_id primary_department_id
id
4109 2093 129
6633 2093 129
6634 2094 129
6635 2095 129
如果我进行上面提到的操作,我会
ipdb> data = dataframe.unstack().to_sparse().to_coo()[0]
ipdb> data
<2x4 sparse matrix of type '<type 'numpy.int64'>'
with 8 stored elements in COOrdinate format>
ipdb> print data
(0, 0) 2093
(0, 1) 2093
(0, 2) 2094
(0, 3) 2095
(1, 0) 129
(1, 1) 129
(1, 2) 129
(1, 3) 129
但我需要
ipdb> print data
(4109, 0) 2093
(6633, 0) 2093
(6634, 0) 2094
etc.
我愿意使用任何其他库或依赖项。
似乎有一个question that asks for the reverse operation,但我还没有找到解决方案。
答案 0 :(得分:2)
我没有安装pandas
,因此无法从数据框开始。但是我们假设我从dataframe
中提取了一个numpy数组(不是像values
这样的方法或属性吗?):
In [40]: D
Out[40]:
array([[4109, 2093], # could be other columns
[6633, 2093],
[6634, 2094],
[6635, 2095]])
从中制作稀疏矩阵是直截了当的 - 我只需要提取或构造3个数组:
In [41]: M=sparse.coo_matrix((D[:,1], (D[:,0], np.zeros(D.shape[0]))),
shape=(7000,1))
In [42]: M
Out[42]:
<7000x1 sparse matrix of type '<class 'numpy.int32'>'
with 4 stored elements in COOrdinate format>
In [43]: print(M)
(4109, 0) 2093
(6633, 0) 2093
(6634, 0) 2094
(6635, 0) 2095
=======================
推广到两个'数据'列
In [70]: D
Out[70]:
array([[4109, 2093, 128],
[6633, 2093, 129],
[6634, 2094, 127],
[6635, 2095, 126]])
In [76]: i,j,data=[],[],[]
In [77]: for col in range(1,D.shape[1]):
i.extend(D[:,0])
j.extend(np.zeros(D.shape[0],int)+(col-1))
data.extend(D[:,col])
....:
In [78]: i
Out[78]: [4109, 6633, 6634, 6635, 4109, 6633, 6634, 6635]
In [79]: j
Out[79]: [0, 0, 0, 0, 1, 1, 1, 1]
In [80]: data
Out[80]: [2093, 2093, 2094, 2095, 128, 129, 127, 126]
In [83]: M=sparse.coo_matrix((data,(i,j)),shape=(7000,D.shape[1]-1))
In [84]: M
Out[84]:
<7000x2 sparse matrix of type '<class 'numpy.int32'>'
with 8 stored elements in COOrdinate format>
In [85]: print(M)
(4109, 0) 2093
(6633, 0) 2093
(6634, 0) 2094
(6635, 0) 2095
(4109, 1) 128
(6633, 1) 129
(6634, 1) 127
(6635, 1) 126
我怀疑你也可以为每一列制作单独的矩阵,并将它们与sparse.bmat
(块)机制结合起来,但我最熟悉coo
格式。
请参阅 Compiling n submatrices into an NxN matrix in numpy
从子矩阵构建大型稀疏矩阵的另一个例子(这里它们重叠)。在那里,我找到了一种通过更快的阵列操作来连接块的方法。这可能是这样做的。但我怀疑在几列(以及extend
多行)上的迭代是快速的。
使用bmat
我可以构建相同的东西:
In [98]: I, J = D[:,0], np.zeros(D.shape[0],int)
In [99]: M1=sparse.coo_matrix((D[:,1],(I, J)), shape=(7000,1))
In [100]: M2=sparse.coo_matrix((D[:,2],(I, J)), shape=(7000,1))
In [101]: print(sparse.bmat([[M1,M2]]))
(4109, 0) 2093
(6633, 0) 2093
(6634, 0) 2094
(6635, 0) 2095
(4109, 1) 128
(6633, 1) 129
(6634, 1) 127
(6635, 1) 126
答案 1 :(得分:1)
一个简单的解决方案是:
import numpy as np
import pandas as pd
df = pd.DataFrame(data = [[2093, 129], [2093, 129], [2094, 129], [2095, 129]], index = [4109, 6633, 6634, 6635], columns = ['instructor_id', 'primary_department_id'])
from scipy.sparse import lil_matrix
sparse_matrix = lil_matrix((df.index.max()+1, len(df.columns)))
for k, column_name in enumerate(df.columns):
sparse_matrix[df.index.values, np.full(len(df), k)] = df[column_name].values
如果您想使用压缩格式,可以直接转换它:
sparse_matrix = sparse_matrix.tocsc()