Python科学计算(第2版)
上QQ阅读APP看书,第一时间看更新

3.8.1 稀疏矩阵的存储形式

scipy.sparse中提供了多种表示稀疏矩阵的格式,每种格式都有不同的用处,其中dok_matrix和lil_matrix适合逐渐添加元素。

dok_matrix从dict继承而来,它采用字典保存矩阵中的非零元素:字典的键是一个保存元素(行,列)信息的元组,其对应的值为矩阵中位于(行,列)中的元素值。显然字典格式的稀疏矩阵很适合单个元素的添加、删除和存取操作。通常用来逐个添加非零元素,然后转换成其他支持快速运算的格式。

    from scipy import sparse
    a = sparse.dok_matrix((10, 5))
    a[2:5, 3] = 1.0, 2.0, 3.0
    print a.keys( )
    print a.values( )
    [(2, 3), (3, 3), (4, 3)]
    [1.0, 2.0, 3.0]

lil_matrix使用两个列表保存非零元素。data保存每行中的非零元素,rows保存非零元素所在的列。这种格式也很适合逐个添加元素,并且能快速获取行相关的数据。

    b = sparse.lil_matrix((10, 5))
    b[2, 3] = 1.0
    b[3, 4] = 2.0
    b[3, 2] = 3.0
    print b.data
    print b.rows
    [[ ] [ ] [1.0] [3.0, 2.0] [ ] [ ] [ ] [ ] [ ] [ ]]
    [[ ] [ ] [3] [2, 4] [ ] [ ] [ ] [ ] [ ] [ ]]

coo_matrix采用三个数组row、col和data保存非零元素的信息。这三个数组的长度相同,row保存元素的行,col保存元素的列,data保存元素的值。coo_matrix不支持元素的存取和增删,一旦创建后,除了将之转换成其他格式的矩阵,几乎无法对其做任何操作和矩阵运算。

coo_matrix支持重复元素,即同一行列坐标可以出现多次,当转换为其他格式的矩阵时,将对同一行列坐标对应的多个值进行求和。在下面的例子中,(2, 3)对应两个值:1和10。在将其转换为ndarray数组时把这两个值加在一起,所以最终矩阵中(2, 3)坐标上的值为11。

许多稀疏矩阵的数据都是采用这种格式保存在文件中的,例如某个CSV文件中可能有这样三列:“用户ID,商品ID,评价值”。采用numpy.loadtxt或pandas.read_csv将数据读入之后,可以通过coo_matrix快速将其转换成稀疏矩阵:矩阵的每行对应一位用户,每列对应一件商品,而元素值为用户对商品的评价。

    row = [2, 3, 3, 2]
    col = [3, 4, 2, 3]
    data = [1, 2, 3, 10]
    c = sparse.coo_matrix((data, (row, col)), shape=(5, 6))
    print c.col, c.row, c.data
    print c.toarray( )
    [3 4 2 3] [2 3 3 2] [ 1  2  3 10]
    [[ 0  0  0  0  0  0]
     [ 0  0  0  0  0  0]
     [ 0  0  0 11  0  0]
     [ 0  0  3  0  2  0]
     [ 0  0  0  0  0  0]]