将稀疏方阵拆分为块

Split a sparse square matrix into blocks

我有一个 <class 'scipy.sparse.csr.csr_matrix'> 类型和大小 = 400 x 400 的带状稀疏方阵 A。我想将其拆分为每个大小为 200 x 200 的方块矩阵。比如第一个块

block1 = A[0:200, 0:200]
block2 = A[100:300, 100:300]
block3 = A[200:400, 200:400]

有关切片的相同信息存储在元组列表中。

 [(0,200), (100, 300), (200, 400)]

关于如何拆分备用方阵的建议将非常有用。

您可以转换为常规数组然后拆分它:

from scipy.sparse import csr_matrix
import numpy as np

row = np.arange(400)[::2]
col = np.arange(400)[1::2]
data = np.random.randint(1, 10, (200))
compressed_matrix = csr_matrix((data, (row, col)), shape=(400, 400))

# Convert to a regular array
m = compressed_matrix.toarray()
# Split the matrix
sl = [(0,200), (100, 300), (200, 400)]
blocks = [m[i, i] for i in map(lambda x: slice(*x), sl)]

如果需要,您可以将每个块转换回压缩矩阵:

blocks_csr = list(map(csr_matrix, blocks))

代码说明

块的创建基于 list comprehension 和基本切片。 每个输入元组被转换为一个 slice 对象,只创建一系列行和列索引,对应于要 selected 的元素;在这个答案中,这足以 select 请求的块平方矩阵。使用扩展索引语法时会生成切片对象:明确地说,a[start:stop:step] 将创建等同于 slice(start, stop, step) 的切片对象。在我们的例子中,它们用于根据我们要提取的矩阵动态更改要 selected 的索引。因此,如果您考虑第一个块,m[i, i] 等同于 m[0:200, 0:200].

Slice 对象是 numpy 数组的 basic indexing, so a view of the original array is created, rather than a copy (this means that if you modify the view, also the original array will be modified: you can easily create a copy of the original data using the copy 方法的一种形式。

map对象用于从输入元组生成切片对象; map 将作为其第一个参数提供的函数应用于其第二个参数的所有元素。 lambda 用于创建匿名函数,即没有名称定义的函数。匿名函数可用于完成您不想在标准函数中编写代码的特定任务,因为您不会重用它们或者您只需要很短的时间,如本代码示例中所示。它们使代码更紧凑,而不是定义对应的函数。

*x 被称为 unpacking,即您从元组中提取、解包元素。假设你有一个函数f和一个元组a = (1, 2, 3),那么f(*a)就等价于f(1, 2, 3)(可以看到,拆包可以认为是去掉了一层括号).

所以,回过头来看代码:

blocks = [  # this is a list comprehension
    m[i, i]  # basic slicing of the input array
    for i in map(  # map apply a function to all the item of a list
        lambda x: slice(*x), sl  # creating a slice object out of the provided index ranges
    )
]