将Python稀疏矩阵字典转换为Scipy稀疏矩阵

5
我将使用Python的scikit-learn进行文档聚类,目前我拥有一个存储在dict对象中的稀疏矩阵。
例如:
doc_term_dict = { ('d1','t1'): 12,             \
                  ('d2','t3'): 10,             \
                  ('d3','t2'):  5              \
                  }                            # from mysql data table 
<type 'dict'>

我希望使用scikit-learn进行聚类,其中输入矩阵类型为scipy.sparse.csr.csr_matrix

示例:

(0, 2164)   0.245793088885
(0, 2076)   0.205702177467
(0, 2037)   0.193810934784
(0, 2005)   0.14547028437
(0, 1953)   0.153720023365
...
<class 'scipy.sparse.csr.csr_matrix'>

我找不到一种方法将 dict 转换为这个csr矩阵(我从未使用过 scipy )。


感谢 @dataman 编辑了我的问题。 - chent
4个回答

5

非常简单。首先阅读字典并将键转换为相应的行和列。Scipy支持(并推荐) COO-rdinate format 用于稀疏矩阵。

传递datarowcolumn,其中A [row [k],column [k] = data [k](对于所有k)定义矩阵。然后让Scipy将其转换为CSR。

请检查我是否按您所需的方式拥有行和列,我可能会对它们进行转置。我还假设输入将是基于1的索引。

我的代码如下打印:

(0, 0)        12
(1, 2)        10
(2, 1)        5

代码:

#!/usr/bin/env python3
#https://dev59.com/2oTba4cB1Zd3GeqP2zat

from scipy.sparse import csr_matrix, coo_matrix

def convert(term_dict):
    ''' Convert a dictionary with elements of form ('d1', 't1'): 12 to a CSR type matrix.
    The element ('d1', 't1'): 12 becomes entry (0, 0) = 12.
    * Conversion from 1-indexed to 0-indexed.
    * d is row
    * t is column.
    '''
    # Create the appropriate format for the COO format.
    data = []
    row = []
    col = []
    for k, v in term_dict.items():
        r = int(k[0][1:])
        c = int(k[1][1:])
        data.append(v)
        row.append(r-1)
        col.append(c-1)
    # Create the COO-matrix
    coo = coo_matrix((data,(row,col)))
    # Let Scipy convert COO to CSR format and return
    return csr_matrix(coo)

if __name__=='__main__':
    doc_term_dict = { ('d1','t1'): 12,             \
                ('d2','t3'): 10,             \
                ('d3','t2'):  5              \
                }   
    print(convert(doc_term_dict))

2
我们可以简化@Unapiedra(优秀的)回答的内容:

我们可以让@Unapiedra(非常好的)回答变得更加简洁:

from scipy.sparse import csr_matrix
def _dict_to_csr(term_dict):
    term_dict_v = list(term_dict.itervalues())
    term_dict_k = list(term_dict.iterkeys())
    shape = list(repeat(np.asarray(term_dict_k).max() + 1,2))
    csr = csr_matrix((term_dict_v, zip(*term_dict_k)), shape = shape)
    return csr

0

和 @carsonc 一样,但适用于 Python 3.X:

from scipy.sparse import csr_matrix
def _dict_to_csr(term_dict):
    term_dict_v = term_dict.values()
    term_dict_k = term_dict.keys()
    term_dict_k_zip = zip(*term_dict_k)
    term_dict_k_zip_list = list(term_dict_k_zip)

    shape = (len(term_dict_k_zip_list[0]), len(term_dict_k_zip_list[1]))
    csr = csr_matrix((list(term_dict_v), list(map(list, zip(*term_dict_k)))), shape = shape)
    return csr

0
一种替代方法是使用np.fromiter,作为使用list存储元素的替代方案。
from scipy.sparse import csr_matrix
import numpy as np

def _dict_to_csr(term_dict, shape=None):

    data = np.fromiter(term_dict.values(), dtype=np.float32)
    rows_tuple, columns_tuple = zip(*term_dict.keys())
    rows = np.fromiter(rows_tuple, dtype=int)
    columns = np.fromiter(columns_tuple, dtype=int)
    
    return csr_matrix((data, (rows, columns)), shape=shape)

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