我正在处理一些相当大的稀疏矩阵(从 5000x5000 到 20000x20000),并且需要找到一种有效的方法以灵活的方式连接矩阵,以便从单独的部分构造随机矩阵。
现在我正在使用以下方法来连接四个矩阵,但效率非常低。有没有更好的方法来做到这一点而不涉及转换为密集矩阵?
rmat[0:m1.shape[0],0:m1.shape[1]] = m1
rmat[m1.shape[0]:rmat.shape[0],m1.shape[1]:rmat.shape[1]] = m2
rmat[0:m1.shape[0],m1.shape[1]:rmat.shape[1]] = bridge
rmat[m1.shape[0]:rmat.shape[0],0:m1.shape[1]] = bridge.transpose()
阿莫斯的回答已经不再必要了。如果输入矩阵采用 csr 或 csc 格式,并且所需的输出格式设置为无或与输入矩阵相同的格式,Scipy 现在会在内部执行类似的操作。分别使用
scipy.sparse.vstack
或 scipy.sparse.hstack
垂直堆叠 csr 格式的矩阵或水平堆叠 csc 格式的矩阵非常高效。
使用 hstack、vstack 或 concatenate 比连接内部数据对象本身要慢得多。原因是 hstack/vstack 将稀疏矩阵转换为 coo 格式,当矩阵非常大且不是 coo 格式时,这可能会非常慢。这是连接csc矩阵的代码,类似的方法可以用于csr矩阵:
def concatenate_csc_matrices_by_columns(matrix1, matrix2):
new_data = np.concatenate((matrix1.data, matrix2.data))
new_indices = np.concatenate((matrix1.indices, matrix2.indices))
new_ind_ptr = matrix2.indptr + len(matrix1.data)
new_ind_ptr = new_ind_ptr[1:]
new_ind_ptr = np.concatenate((matrix1.indptr, new_ind_ptr))
return csc_matrix((new_data, new_indices, new_ind_ptr))
好的,我找到答案了。使用 scipy.sparse.coo_matrix 比使用 lil_matrix 快得多。我将矩阵转换为 coo(无痛且快速),然后在添加正确的填充后连接数据、行和列。
data = scipy.concatenate((m1S.data,bridgeS.data,bridgeTS.data,m2S.data))
rows = scipy.concatenate((m1S.row,bridgeS.row,bridgeTS.row + m1S.shape[0],m2S.row + m1S.shape[0]))
cols = scipy.concatenate((m1S.col,bridgeS.col+ m1S.shape[1],bridgeTS.col ,m2S.col + m1S.shape[1]))
scipy.sparse.coo_matrix((data,(rows,cols)),shape=(m1S.shape[0]+m2S.shape[0],m1S.shape[1]+m2S.shape[1]) )
Amos 的解决方案仅适用于两个矩阵,如果其中一个没有条目,则会失败,这在我的用例中很常见。此版本没有这些限制:
def concatenate_sparse_csc_matrices(list_of_matrices):
num_rows = list_of_matrices[0].shape[0]
num_cols = sum(m.shape[1] for m in list_of_matrices)
data = []
indices = []
indptr_diff = [[0]]
for m in list_of_matrices:
if m.nnz > 0:
data.append(m.data)
indices.append(m.indices)
indptr_diff.append(np.diff(m.indptr))
else:
indptr_diff.append([0] * m.shape[1])
if data:
data = np.concatenate(data)
if indices:
indices = np.concatenate(indices)
indptr = np.cumsum(np.concatenate(indptr_diff))
concatenated_matrix = csc_matrix((data, indices, indptr), shape=(num_rows, num_cols))
return concatenated_matrix