很遗憾,似乎SciPy没有提供这种稀疏矩阵操作的工具。但是,通过巧妙地操作条目的索引和数据,可以直接模拟
np.diff(x,n)
。
给定维度为
MxN
的二维NumPy数组(矩阵),
np.diff()
将每个列(列索引为
y
)乘以
-1
并将下一列添加到它(列索引为
y+1
)。顺序为
k
的差分只是对
1
级差分进行
k
次迭代应用。顺序为
0
的差分只是返回输入矩阵。
下面的方法利用这一点,通过
sum_duplicates()
迭代地消除重复条目,减少一列,并过滤非有效索引。
def csc_diff(x, n):
'''Emulates np.diff(x,n) for a sparse matrix by iteratively taking difference of order 1'''
assert isinstance(x, csc_matrix) or (isinstance(x, np.ndarray) & len(x.shape) == 2), "Input matrix must be a 2D np.ndarray or csc_matrix."
assert isinstance(n, int) & n >= 0, "Integer n must be larger or equal to 0."
if n >= x.shape[1]:
return csc_matrix(([], ([], [])), shape=(x.shape[0], 0))
if isinstance(x, np.ndarray):
x = csc_matrix(x)
if(n > 0):
for k in range(1,n+1):
M, N = x.shape
idx, idy = x.nonzero()
dat = x.data
idx = np.concatenate((idx, idx))
idy = np.concatenate((idy, idy-1))
dat = np.concatenate(((-1)*dat, dat))
validInd = (0<=idy) & (idy<N-1)
x_diff = csc_matrix((dat[validInd], (idx[validInd], idy[validInd])), shape=(M, N-1))
x_diff.sum_duplicates()
x = x_diff
return x
此外,当差分阶数大于或等于输入矩阵的列数时,该方法会输出一个维度为
Mx0
的空
csc_matrix
。这就是为什么输出结果是相同的原因,请参见。
csc_diff(x, 2).toarray()
> array([[ 1., 0.],
[-2., 1.],
[ 1., -2.],
[ 0., 1.]])
这与
np.diff(x.toarray(), 2)
> array([[ 1., 0.],
[-2., 1.],
[ 1., -2.],
[ 0., 1.]])
这个等式对于其他差分阶数也成立。
(csc_diff(x, 0).toarray() == np.diff(x.toarray(), 0)).all()
>True
(csc_diff(x, 3).toarray() == np.diff(x.toarray(), 3)).all()
>True
(csc_diff(x, 13).toarray() == np.diff(x.toarray(), 13)).all()
>True
np.diff
吗?你不能只用几条对角线创建矩阵吗? - hpauljdiff
代码并进行自己的计算。从稀疏的角度来看,这并不是很大。稀疏矩阵乘法和对非零项进行操作的ufunc是很好的选择。但对于这种类型的计算来说,并没有节省多少时间,如果有的话。 - hpaulj