计算一个csr
稀疏矩阵的选定列(或行)总和的最佳方法是使用另一个稀疏矩阵的矩阵乘积,该矩阵在要求和的位置有1。事实上csr
总和(一整行或列)的工作原理是矩阵的产品,和索引行(或列)也与产品完成(https://stackoverflow.com/a/39500986/901925)
所以我组的日期排列,并利用这些信息构造总和'面具'。
为了讨论起见,考虑这个密集阵:
In [117]: A
Out[117]:
array([[0, 2, 7, 5, 0, 7, 0, 8, 0, 7],
[0, 0, 3, 0, 0, 1, 2, 6, 0, 0],
[0, 0, 0, 0, 2, 0, 5, 0, 0, 0],
[4, 0, 6, 0, 0, 5, 0, 0, 1, 4],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 7, 0, 8, 1, 0, 9, 0, 2, 4],
[9, 0, 8, 4, 0, 0, 0, 0, 9, 7],
[0, 0, 0, 1, 2, 0, 2, 0, 4, 7],
[3, 0, 1, 0, 0, 0, 0, 0, 0, 2],
[0, 0, 1, 8, 5, 0, 0, 0, 8, 0]])
做一个稀疏副本:
In [118]: M=sparse.csr_matrix(A)
产生一些群体的基础上,最后一列; collections.defaultdict
就是做了一个非常方便的工具:
In [119]: grps=defaultdict(list)
In [120]: for i,v in enumerate(A[:,-1]):
...: grps[v].append(i)
In [121]: grps
Out[121]: defaultdict(list, {0: [1, 2, 4, 9], 2: [8], 4: [3, 5], 7: [0, 6, 7]})
我可以遍历这些群体,横跨这些行收集的M
行,和生产:
In [122]: {k:M[v,:].sum(axis=0) for k, v in grps.items()}
Out[122]:
{0: matrix([[0, 0, 4, 8, 7, 2, 7, 6, 8, 0]], dtype=int32),
2: matrix([[3, 0, 1, 0, 0, 0, 0, 0, 0, 2]], dtype=int32),
4: matrix([[4, 7, 6, 8, 1, 5, 9, 0, 3, 8]], dtype=int32),
7: matrix([[ 9, 2, 15, 10, 2, 7, 2, 8, 13, 21]], dtype=int32)}
在最后一列,值包括2 * 4和3 * 7
因此,有2个任务 - 收集组,无论是使用此defaultdict还是itertools.groupby
(在这种情况下需要排序)或pandas
groupby。其次是这些行和汇总。这个词典迭代在概念上很简单。
掩蔽矩阵可能的工作是这样的:
In [141]: mask=np.zeros((10,10),int)
In [142]: for i,v in enumerate(A[:,-1]): # same sort of iteration
...: mask[v,i]=1
...:
In [143]: Mask=sparse.csr_matrix(mask)
...
In [145]: Mask.A
Out[145]:
array([[0, 1, 1, 0, 1, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 1, 0],
....
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
In [146]: (Mask*M).A
Out[146]:
array([[ 0, 0, 4, 8, 7, 2, 7, 6, 8, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 3, 0, 1, 0, 0, 0, 0, 0, 0, 2],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 4, 7, 6, 8, 1, 5, 9, 0, 3, 8],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 9, 2, 15, 10, 2, 7, 2, 8, 13, 21],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
这Mask*M
具有相同的值作为字典行,但额外的0。我可以与lil
格式隔离非零值:
In [147]: (Mask*M).tolil().data
Out[147]:
array([[4, 8, 7, 2, 7, 6, 8], [], [3, 1, 2], [],
[4, 7, 6, 8, 1, 5, 9, 3, 8], [], [],
[9, 2, 15, 10, 2, 7, 2, 8, 13, 21], [], []], dtype=object)
我可以直接使用输入的coo
稀疏样式构造Mask
矩阵:
Mask = sparse.csr_matrix((np.ones(A.shape[0],int),
(A[:,-1], np.arange(A.shape[0]))), shape=(A.shape))
这应该是更快和避免记忆误差(无环或大密集阵列)。
你在说'熊猫''groupby'吗?你能给一个密集阵列的工作例子吗?有一种熊猫稀疏格式,但它与稀疏矩阵的交互仍在开发中。 – hpaulj
第181列 - 稀疏与否? – hpaulj
第181列(groups_X)是'scipy.sparse.csc.csc_matrix',但实际上它是密集的,因为每个观察都有一个日期。 –