我的情况如下:
我有一系列的结果,比方说
S = np.array([2,3,10,-1,12,1,2,4,4])
,我想根据可能重复元素(没有特定模式)的列索引数组插入scipy.sparse.lil
_ matrix M
的最后一行,例如:
j = np.array([3,4,5,14,15,16,3,4,5])
。
当重复列索引时,S
中相应值的总和应插入矩阵M
中。因此,在上面的示例中,结果[4,7,14]
应放在[3,4,5]
的最后一行的M
列中。换句话说,我想实现类似的东西:
M[-1,j] = np.array([2+2,3+4,10+4,-1,12,1])
。
计算速度对我的程序非常重要,因此我应该避免使用循环。期待您的聪明解决方案!谢谢!
答案 0 :(得分:0)
您可以使用defaultdict将M列索引映射到它们的值,并使用map
函数更新此defaultdict,如下所示:
from collections import defaultdict
d = defaultdict(int) #Use your array type here
def f(j, s):
d[j] += s
map(f, j, S)
M[-1, d.keys()] = d.values() #keys and values are always in the same order
如果您不想无用地创建map
列表,则可以使用filter
而不是None
:
d = defaultdict(int) #Use your array type here
def g(e):
d[e[1]] += S[e[0]]
filter(g, enumerate(j))
M[-1, d.keys()] = d.values() #keys and values are always in the same
答案 1 :(得分:0)
这种求和是sparse
矩阵的正常行为,尤其是csr
格式。
定义3个输入数组:
In [408]: S = np.array([2,3,10,-1,12,1,2,4,4])
In [409]: j=np.array([3,4,5,14,15,16,3,4,5])
In [410]: i=np.ones(S.shape,int)
coo
格式按原样使用这3个数组,无需更改
In [411]: c0=sparse.coo_matrix((S,(i,j)))
In [412]: c0.data
Out[412]: array([ 2, 3, 10, -1, 12, 1, 2, 4, 4])
但是当转换为csr
格式时,它会对重复的索引求和:
In [413]: c1=c0.tocsr()
In [414]: c1.data
Out[414]: array([ 4, 7, 14, -1, 12, 1], dtype=int32)
In [415]: c1.A
Out[415]:
array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 4, 7, 14, 0, 0, 0, 0, 0, 0, 0, 0, -1, 12, 1]], dtype=int32)
将coo
转换为密集或数组c0.A
时也会进行求和。
以及转换为lil
时:
In [419]: cl=c0.tolil()
In [420]: cl.data
Out[420]: array([[], [4, 7, 14, -1, 12, 1]], dtype=object)
In [421]: cl.rows
Out[421]: array([[], [3, 4, 5, 14, 15, 16]], dtype=object)
lil_matrix
不会直接接受(data,(i,j))
输入,因此如果您是目标,则必须通过coo
。
http://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.sparse.coo_matrix.html
默认情况下,转换为CSR或CSC格式时,重复(i,j)条目将汇总在一起。这有利于有限元矩阵等的有效构造。 (见例)
要在现有lil
中插入,请使用中间csr
:
In [443]: L=sparse.lil_matrix((3,17),dtype=S.dtype)
In [444]: L[-1,:]=sparse.csr_matrix((S,(np.zeros(S.shape),j)))
In [445]: L.A
Out[445]:
array([[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, 4, 7, 14, 0, 0, 0, 0, 0, 0, 0, 0, -1, 12, 1]])
此声明比使用csr_matrix
的声明更快;
L[-1,:]=sparse.coo_matrix((S,(np.zeros(S.shape),j)))
如果您真的担心速度,请检查L.__setitem__
。在手边看起来它通常会将稀疏矩阵转换为数组
L[-1,:]=sparse.coo_matrix((S,(np.zeros(S.shape),j))).A
需要同样的时间。对于像这样的小测试用例,创建中间矩阵的开销可能会花费任何时间来添加这些重复索引。
通常,无论是否进行此求和,向现有稀疏矩阵插入或附加值都很慢。在可能的情况下,最好先为整个矩阵创建data
,i
和j
数组,然后再制作稀疏矩阵。