在 python 中添加两个不同形状的 `csc` 稀疏矩阵
Adding two `csc` sparse matrices of different shapes in python
所以我有两个 csc
不同形状的矩阵需要加在一起。矩阵如下所示:
current_flows = (7005, 1001) 50.0
(8259, 1001) 65.0
(14007, 1001) 45.0
(9971, 1002) 80.0
: :
(69003, 211148) 0.0
result_flows = (7005, 1001) 40
(14007, 1001) 20
(9971, 1002) 35
: :
(71136, 71137) 90
final_flows = current_flows + result_flows
如某些行和列 ID 所示:(7005, 1001), (14007, 1001), (9971, 1002)
矩阵确实有共同的元素。尽管它们的形状不同,但基于它们的最终行和列 ID。
我想将两个矩阵相加,同时保留较大矩阵 (current_flows
) 的形状并保持 current_flows
的值相同,而 result_flows
则不同具有匹配 current_flows
的行和列 ID。因此,final_flows
的行和列索引将扩展到:(69003, 211148)
,即使 result_flows
仅扩展到 (71136, 71137)
因此,我希望我的输出是:
final_flows = (7005, 1001) 90.0
(8259, 1001) 65.0
(14007, 1001) 65.0
(9971, 1002) 115.0
: :
(71136, 71137) 90
(69003, 211148) 0.0
如果您想进一步说明,请告诉我,谢谢!
您应该将矩阵转换为 dok
class。然后索引和数据将存储为字典。请注意,第二个矩阵 result_flows
不应具有索引大于 current_flows
形状的值。
(已编辑,感谢@hpaulj 评论)。
from scipy import sparse
current_flows = sparse.dok_matrix([[0, 0, 1],
[2, 0, 4],
[0, 0, 0],
[3, 0, 0]]
)
result_flows = sparse.dok_matrix([[0, 0, 0, 0, 0],
[-3, 0, 0, 0, 0],
[0, -2, 0, 0, 0]]
)
current_flows.update((k, v + current_flows.get(k)) for k, v in result_flows.items())
current_flows.todense()
Out[108]: matrix([[ 0, 0, 1],
[-1, 0, 4],
[ 0, -2, 0],
[ 3, 0, 0]])
当通过 coo
或输入的 coo 样式 (data,(row,col))
定义矩阵时,重复的条目会被求和。刚度矩阵(用于 pde 解决方案)的创建者经常利用这一点。
这是一个使用它的函数。我将矩阵转换为 coo
格式(如果需要),连接它们的属性,然后构建一个新矩阵。
def with_coo(x,y):
x=x.tocoo()
y=y.tocoo()
d = np.concatenate((x.data, y.data))
r = np.concatenate((x.row, y.row))
c = np.concatenate((x.col, y.col))
C = sparse.coo_matrix((d,(r,c)))
return C
以@Vadim 为例:
In [59]: C_csc=current_flows.tocsc()
In [60]: R_csc=result_flows.tocsc()
In [61]: with_coo(C_csc, R_csc).tocsc().A
Out[61]:
array([[ 0, 0, 1],
[-1, 0, 4],
[ 0, -2, 0],
[ 3, 0, 0]], dtype=int32)
在安排时间时我们必须小心,因为格式转换很重要,例如
In [70]: timeit C_csc.tocoo()
10000 loops, best of 3: 128 µs per loop
In [71]: timeit C_csc.todok()
1000 loops, best of 3: 258 µs per loop
瓦迪姆的两个选择
def with_dok(x, y):
for k in y.keys(): # no has_key in py3
if k in x:
x[k] += y[k]
else:
x[k] = y[k]
return x
def with_update(x,y):
x.update((k, v+x.get(k)) for k, v in y.items())
return x
从 csc
格式开始:
In [74]: timeit with_coo(C_csc,R_csc).tocsc()
1000 loops, best of 3: 629 µs per loop
In [76]: timeit with_update(C_csc.todok(),R_csc.todok()).tocsc()
1000 loops, best of 3: 1 ms per loop
In [77]: timeit with_dok(C_csc.todok(),R_csc.todok()).tocsc()
1000 loops, best of 3: 1.12 ms per loop
我猜测我的 coo
方法会更好地扩展 - 但这只是目前的猜测。
不考虑转换,dok
更新看起来更好。 y
只有 2 项,它不做任何复制 - 它直接更改 x
。
In [78]: %%timeit x=C_csc.todok(); y=R_csc.todok()
....: with_update(x, y)
....:
10000 loops, best of 3: 33.6 µs per loop
In [79]: %%timeit x=C_csc.tocoo(); y=R_csc.tocoo()
with_coo(x, y)
....:
10000 loops, best of 3: 138 µs per loop
================
dok_matrix
的 __add__
方法包含(如果 other
也是 dok
)。有评论想知道他们是否需要检查 shape
.
new = dok_matrix(self.shape, dtype=res_dtype)
new.update(self)
for key in other.keys():
new[key] += other[key]
[如果我先更改 y
的形状,我可以绕过 shape
签入 x+y
,例如y._shape = x.shape
。这是笨拙的,只能在原始形状的合理范围内工作。并且可能不会比 with_update
方法快。 dok
比 csr
或 csc
更适合这种形状变化。]
如果 other
不是 dok
,它是 self.tocsc()+other
。
对于匹配形状,求和时间为
In [91]: timeit current_flows+current_flows
1000 loops, best of 3: 413 µs per loop
In [92]: timeit C_csc+C_csc
1000 loops, best of 3: 223 µs per loop
所以我有两个 csc
不同形状的矩阵需要加在一起。矩阵如下所示:
current_flows = (7005, 1001) 50.0
(8259, 1001) 65.0
(14007, 1001) 45.0
(9971, 1002) 80.0
: :
(69003, 211148) 0.0
result_flows = (7005, 1001) 40
(14007, 1001) 20
(9971, 1002) 35
: :
(71136, 71137) 90
final_flows = current_flows + result_flows
如某些行和列 ID 所示:(7005, 1001), (14007, 1001), (9971, 1002)
矩阵确实有共同的元素。尽管它们的形状不同,但基于它们的最终行和列 ID。
我想将两个矩阵相加,同时保留较大矩阵 (current_flows
) 的形状并保持 current_flows
的值相同,而 result_flows
则不同具有匹配 current_flows
的行和列 ID。因此,final_flows
的行和列索引将扩展到:(69003, 211148)
,即使 result_flows
仅扩展到 (71136, 71137)
因此,我希望我的输出是:
final_flows = (7005, 1001) 90.0
(8259, 1001) 65.0
(14007, 1001) 65.0
(9971, 1002) 115.0
: :
(71136, 71137) 90
(69003, 211148) 0.0
如果您想进一步说明,请告诉我,谢谢!
您应该将矩阵转换为 dok
class。然后索引和数据将存储为字典。请注意,第二个矩阵 result_flows
不应具有索引大于 current_flows
形状的值。
(已编辑,感谢@hpaulj 评论)。
from scipy import sparse
current_flows = sparse.dok_matrix([[0, 0, 1],
[2, 0, 4],
[0, 0, 0],
[3, 0, 0]]
)
result_flows = sparse.dok_matrix([[0, 0, 0, 0, 0],
[-3, 0, 0, 0, 0],
[0, -2, 0, 0, 0]]
)
current_flows.update((k, v + current_flows.get(k)) for k, v in result_flows.items())
current_flows.todense()
Out[108]: matrix([[ 0, 0, 1],
[-1, 0, 4],
[ 0, -2, 0],
[ 3, 0, 0]])
当通过 coo
或输入的 coo 样式 (data,(row,col))
定义矩阵时,重复的条目会被求和。刚度矩阵(用于 pde 解决方案)的创建者经常利用这一点。
这是一个使用它的函数。我将矩阵转换为 coo
格式(如果需要),连接它们的属性,然后构建一个新矩阵。
def with_coo(x,y):
x=x.tocoo()
y=y.tocoo()
d = np.concatenate((x.data, y.data))
r = np.concatenate((x.row, y.row))
c = np.concatenate((x.col, y.col))
C = sparse.coo_matrix((d,(r,c)))
return C
以@Vadim 为例:
In [59]: C_csc=current_flows.tocsc()
In [60]: R_csc=result_flows.tocsc()
In [61]: with_coo(C_csc, R_csc).tocsc().A
Out[61]:
array([[ 0, 0, 1],
[-1, 0, 4],
[ 0, -2, 0],
[ 3, 0, 0]], dtype=int32)
在安排时间时我们必须小心,因为格式转换很重要,例如
In [70]: timeit C_csc.tocoo()
10000 loops, best of 3: 128 µs per loop
In [71]: timeit C_csc.todok()
1000 loops, best of 3: 258 µs per loop
瓦迪姆的两个选择
def with_dok(x, y):
for k in y.keys(): # no has_key in py3
if k in x:
x[k] += y[k]
else:
x[k] = y[k]
return x
def with_update(x,y):
x.update((k, v+x.get(k)) for k, v in y.items())
return x
从 csc
格式开始:
In [74]: timeit with_coo(C_csc,R_csc).tocsc()
1000 loops, best of 3: 629 µs per loop
In [76]: timeit with_update(C_csc.todok(),R_csc.todok()).tocsc()
1000 loops, best of 3: 1 ms per loop
In [77]: timeit with_dok(C_csc.todok(),R_csc.todok()).tocsc()
1000 loops, best of 3: 1.12 ms per loop
我猜测我的 coo
方法会更好地扩展 - 但这只是目前的猜测。
不考虑转换,dok
更新看起来更好。 y
只有 2 项,它不做任何复制 - 它直接更改 x
。
In [78]: %%timeit x=C_csc.todok(); y=R_csc.todok()
....: with_update(x, y)
....:
10000 loops, best of 3: 33.6 µs per loop
In [79]: %%timeit x=C_csc.tocoo(); y=R_csc.tocoo()
with_coo(x, y)
....:
10000 loops, best of 3: 138 µs per loop
================
dok_matrix
的 __add__
方法包含(如果 other
也是 dok
)。有评论想知道他们是否需要检查 shape
.
new = dok_matrix(self.shape, dtype=res_dtype)
new.update(self)
for key in other.keys():
new[key] += other[key]
[如果我先更改 y
的形状,我可以绕过 shape
签入 x+y
,例如y._shape = x.shape
。这是笨拙的,只能在原始形状的合理范围内工作。并且可能不会比 with_update
方法快。 dok
比 csr
或 csc
更适合这种形状变化。]
如果 other
不是 dok
,它是 self.tocsc()+other
。
对于匹配形状,求和时间为
In [91]: timeit current_flows+current_flows
1000 loops, best of 3: 413 µs per loop
In [92]: timeit C_csc+C_csc
1000 loops, best of 3: 223 µs per loop