稀疏矩阵定义以及存储格式(COO,CSR,CSC)

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了稀疏矩阵定义以及存储格式(COO,CSR,CSC)相关的知识,希望对你有一定的参考价值。

参考技术A

百度百科:在矩阵中,若数值为0的元素数目远远多于非0元素的数目,并且非0元素分布没有规律时,则称该矩阵为稀疏矩阵;与之相反,若非0元素数目占大多数时,则称该矩阵为稠密矩阵。定义非零元素的总数比上矩阵所有元素的总数为矩阵的稠密度。 简单来说,稀疏矩阵就是绝大部分都是0的矩阵 ,只包含很少的非零值.

比如,

上述稀疏矩阵非零元素有9个,26个零值.稀疏性是74%.

稀疏矩阵因为绝大部分都是0元素,如果我们仍然按照普通方式存储,无疑会 浪费很多空间 ;同时如果进行运算时,0元素对最终结果也没有帮助, 增加了许多无效计算 . 因此,我们需要设计出新的存储方式,或者说数据结构来存储稀疏矩阵.比较常见的有:

对于稀疏矩阵的存储,为了达到压缩的目的(节省存储空间),只存储非0元素值,但是也要保留非零元素的位置,方便恢复.所以,我们存储时不仅存储非零元素值,同时存储其坐标位置(row,column). 针对这两者的存储,会出现不同的设计方案.这里主要介绍COO,CSR和CSC存储格式.

我们使用三个数组row,column和data分别用来存储非零元素坐标的row_index,col_index,以及数值.比如:

NNO:The number of nonzero.矩阵非零元素个数. 三个数组的长度都是NNO.data[i]在原稀疏矩阵中的坐标为(row[i],col[i]]).

可以发现,这种存储方式中,row数组和column数组中有一定的重复元素.我们是否可以针对这个冗余特性进一步进行压缩?之后出现CSR,CSC,分别是对row数组和column数组进行了压缩.

对COO稀疏矩阵存储格式的三个数组中的row数组进行压缩.其他两个数组保持不变;三个数组分别是row_ptr,columns和data.其中columns和data数组长度均为NNO(矩阵的非零元素个数). 如何对COO的row进行压缩?

row_ptr存储的是每行的第一个非零元素距离稀疏矩阵第一个元素的偏移位置;

由row_ptr我们可以知道每行非零元素在data中的index范围.第i行的非零元素为data[row_ptr[i]:row_ptr[i+1]],对data数组的切片,不包含data[row_ptr[i+1]];同时第i行非零元素的col坐标分别为columns[row_ptr[i]:row_ptr[i+1]];对data和columns的访问相似,index是相同的.

如上图中,第0行非零元素在data中是data[0:2],就是1,7;列坐标为columns[0:2],就是0,1,第1行非零元素为data[2:4],有两个元素2和8,列坐标分别为columns[2:4],1和2.

方便进行行操作.

和CSR类似.只不过对列进行压缩,row和data保持不变.

方便进行列操作.

将稀疏矩阵转换为熊猫数据框

【中文标题】将稀疏矩阵转换为熊猫数据框【英文标题】:Convert sparse matrix to pandas dataframe 【发布时间】:2021-12-14 00:35:47 【问题描述】:
import numpy as np
from scipy.sparse import csr_matrix

csr = csr_matrix(np.array(
    [[0, 0, 4],
     [1, 0, 0],
     [2, 0, 0],]))

# Return a Coordinate (coo) representation of the csr matrix.
coo = csr.tocoo(copy=False)

# Access `row`, `col` and `data` properties of coo matrix.
df = pd.DataFrame('index': coo.row, 'col': coo.col, 'data': coo.data)[['index', 'col', 'data']]

>>> df.head()
   index  col  data
0    0     2     4
1    1     0     1
2    2     0     2

我尝试将 scipy csr_matrix 矩阵转换为数据框,其中的列代表矩阵的索引、列和数据。

唯一的问题是我上面尝试的方法不会为值为 0 的列生成行。这是我希望输出的样子:

>>> df.head()
   index  col  data
0    0     0     0
1    0     1     0
2    0     2     4
3    1     0     1
4    1     1     0
5    1     2     0
6    2     0     2
7    2     1     0
8    2     2     0

你会看到上面的代码 sn-p 取自this answer in this thread。

我的请求/问题:有没有办法将矩阵转换为 df 并包含值为 0 的矩阵元素?

【问题讨论】:

【参考方案1】:

一种方法是创建一个filling DataFrame 并将其(使用combine_first)与您已有的数据框结合起来:

df = pd.DataFrame('index': coo.row, 'col': coo.col, 'data': coo.data).set_index(["index", "col"])

n_rows, n_cols = coo.shape
rows, cols = map(np.ndarray.flatten, np.mgrid[:n_rows, :n_cols])
filling = pd.DataFrame("index": rows, "col": cols, "data": np.repeat(0, n_rows * n_cols)) \
    .set_index(["index", "col"])

res = df.combine_first(filling).reset_index()

print(res)

输出

   index  col  data
0      0    0   0.0
1      0    1   0.0
2      0    2   4.0
3      1    0   1.0
4      1    1   0.0
5      1    2   0.0
6      2    0   2.0
7      2    1   0.0
8      2    2   0.0

【讨论】:

以上是关于稀疏矩阵定义以及存储格式(COO,CSR,CSC)的主要内容,如果未能解决你的问题,请参考以下文章

SciPySparse稀疏矩阵主要存储格式总结(转载)

scipy常见数据结构:coo_matrix、csc_matrix与csr_matrix

稀疏矩阵(Sparse Matrix)

稀疏矩阵压缩存储:CSR/CSC (Compress Sparse Row/Column)

稀疏矩阵压缩存储:CSR

python系列26:numpy稀疏矩阵笔记