我不知道,如果速度增加不多,但你的迭代可精简为
for i,j in zip(*C):
D[j].add(i)
defaultdict可以为此任务添加一个不错的接触:
In [58]: from collections import defaultdict
In [59]: D=defaultdict(set)
In [60]: for i,j in zip(*C):
D[j].add(i)
In [61]: D
Out[61]: defaultdict(<class 'set'>, {0: {0, 2, 3, 4, 5}, 1: {1, 3, 4}, 2: {1, 2, 6, 7}, 3: {1, 3, 4, 6}, 4: {1, 2, 6, 7}, 5: {0, 2, 3}})
In [62]: dict(D)
Out[62]:
{0: {0, 2, 3, 4, 5},
1: {1, 3, 4},
2: {1, 2, 6, 7},
3: {1, 3, 4, 6},
4: {1, 2, 6, 7},
5: {0, 2, 3}}
带稀疏矩阵的替代方法是lil
格式,该格式将数据保存为列表列表。由于您想按列收集数据,因此请从A.T
(转置)制作矩阵
In [70]: M=sparse.lil_matrix(A.T)
In [71]: M.rows
Out[71]:
array([[0, 2, 3, 4, 5], [1, 3, 4], [1, 2, 6, 7], [1, 3, 4, 6],
[1, 2, 6, 7], [0, 2, 3]], dtype=object)
这些列表相同。
对于这种小的情况下直接迭代比稀疏
In [72]: %%timeit
....: D=defaultdict(set)
....: for i,j in zip(*C):
D[j].add(i)
....:
10000 loops, best of 3: 24.4 µs per loop
In [73]: %%timeit
....: D=[set() for j in range(A.shape[1])]
....: for i,j in zip(*C):
D[j].add(i)
....:
10000 loops, best of 3: 22.9 µs per loop
In [74]: %%timeit
....: M=sparse.lil_matrix(A.T)
....: M.rows
....:
1000 loops, best of 3: 588 µs per loop
In [75]: %%timeit
....: C=sparse.csc_matrix(A)
....: D = [set(C.indices[C.indptr[i]:C.indptr[i+1]]) for i in range(C.shape[1])] ....:
1000 loops, best of 3: 476 µs per loop
更快对于一个大的阵列中,设置时间稀疏矩阵将更少显著。
==========================
我们真的需要set
?在lil
方法的一个变型是转置开始与nonzero
,即通过柱
In [90]: C=np.nonzero(A.T)
# (array([0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5], dtype=int32),
# array([0, 2, 3, 4, 5, 1, 3, 4, 1, 2, 6, 7, 1, 3, 4, 6, 1, 2, 6, 7, 0, 2, 3], dtype=int32))
中的数字都在那里;我们只需将第二个列表拆分为对应于第一个的部分
In [91]: i=np.nonzero(np.diff(C[0]))[0]+1
In [92]: np.split(C[1],i)
Out[92]:
[array([0, 2, 3, 4, 5], dtype=int32),
array([1, 3, 4], dtype=int32),
array([1, 2, 6, 7], dtype=int32),
array([1, 3, 4, 6], dtype=int32),
array([1, 2, 6, 7], dtype=int32),
array([0, 2, 3], dtype=int32)]
这比直接迭代慢,但我怀疑它比较好;可能以及任何稀疏的替代品:
In [96]: %%timeit
C=np.nonzero(A.T)
....: i=np.nonzero(np.diff(C[0]))[0]+1
....: np.split(C[1],i)
....:
10000 loops, best of 3: 55.2 µs per loop
真棒,这方法大约是我原来的代码的两倍。谢谢! – ToneDaBass
在较大的稀疏数组上,我发现'np.nonzero(A)'和'稀疏。csc_matrix(A)'大概在同一时间。它比收集集合的迭代要大得多。 – hpaulj