我花了大约2个小时试图弄清楚发生了什么,但对于我的生活,我无法弄清楚为什么在乘法似乎不起作用时改变矩阵的顺序:
使用Python 2.7x:
import numpy as np
num_segments = 25
num_vintages = 24
# Create a 3d matrix 25 deep x 24r x 24c
mx_loans_new_loans = np.zeros((num_segments, num_vintages, num_vintages))
# Create the multiplication vector - same as the first dimension of 3d matrix
mult_vector = np.arange(10,35)
len(mult_vector)
目的是用mult_vector
填充对角线上的矩阵。
这是我无法绕过的部分。
此版本不符合意图:
for (i, x) in enumerate(mx_loans_new_loans):
np.fill_diagonal(x, 1)
x = x * mult_vector[i]
结果仍然只是在对角线上的1' s原始矩阵吐出。
然而,这个版本确实有效。我所做的就是颠倒enumerate
中的矩阵:
for (i, x) in enumerate(mult_vector):
np.fill_diagonal(mx_loans_new_loans[i], 1)
mx_loans_new_loans[i] = mx_loans_new_loans[i] * x
旁注: 我已经意识到更优化的版本填补了意图:
for (i, x) in enumerate(mx_loans_new_loans):
np.fill_diagonal(x, mult_vector[i])
但有谁知道为什么第一个版本不起作用,但第二个版本呢?我错过了什么?这是广播问题还是更简单?
答案 0 :(得分:2)
mx_loans_new_loans
是3d,(25,24,24)。循环中的x
是(24,24)。 multi_vector
是(25,); multivector[i]
标量。
fill_diagonal
设置x
中的1(就地)。但x = x * mult_vector[i]
用新数组替换x
,并且不会更改原始数据。也就是说,它会重新分配变量x
。
x *= mult_vector[i]
应该更改原始数组中的对角线。
mx_loans_new_loans[i] = ...
更改此子阵列。同样mx_loans_new_loans[i] *= ...
应该也可以。
使用zip
,我们可以迭代两个数组:
In [44]: Z=np.zeros((4,3,3),int)
In [45]: for i,j in zip(Z,np.arange(10,14)):
...: np.fill_diagonal(i,j)
...:
In [46]: Z
Out[46]:
array([[[10, 0, 0],
[ 0, 10, 0],
[ 0, 0, 10]],
[[11, 0, 0],
[ 0, 11, 0],
[ 0, 0, 11]],
[[12, 0, 0],
[ 0, 12, 0],
[ 0, 0, 12]],
[[13, 0, 0],
[ 0, 13, 0],
[ 0, 0, 13]]])
我们可以通过以下方式查看循环中设置的所有对角线:
In [47]: Z[:,np.arange(3),np.arange(3)]
Out[47]:
array([[10, 10, 10],
[11, 11, 11],
[12, 12, 12],
[13, 13, 13]])
用(不太正确)修改它们:
In [48]: Z[:,np.arange(3),np.arange(3)]=np.arange(20,23)
In [49]: Z
Out[49]:
array([[[20, 0, 0],
[ 0, 21, 0],
[ 0, 0, 22]],
[[20, 0, 0],
[ 0, 21, 0],
[ 0, 0, 22]],
[[20, 0, 0],
[ 0, 21, 0],
[ 0, 0, 22]],
[[20, 0, 0],
[ 0, 21, 0],
[ 0, 0, 22]]])
更好:
In [50]: Z[:,np.arange(3),np.arange(3)]=np.arange(20,24)[:,None]
In [51]: Z
Out[51]:
array([[[20, 0, 0],
[ 0, 20, 0],
[ 0, 0, 20]],
[[21, 0, 0],
[ 0, 21, 0],
[ 0, 0, 21]],
[[22, 0, 0],
[ 0, 22, 0],
[ 0, 0, 22]],
[[23, 0, 0],
[ 0, 23, 0],
[ 0, 0, 23]]])
赋值如何更改数组(或不更改)的另一个示例:
In [97]: x = np.zeros((2,3),int)
y
是view
,是查看x
行的一种方式:
In [99]: y = x[0]
In [100]: id(y)
Out[100]: 2877147400
y
的就地更改显示为对x
的更改:
In [101]: y += 3
In [102]: y
Out[102]: array([3, 3, 3])
In [103]: x
Out[103]:
array([[3, 3, 3],
[0, 0, 0]])
但y=
更改为y
会破坏连接。 y
不再是x
的视图(行),而是一个全新的数组。
In [104]: y = y + 3
In [105]: y
Out[105]: array([6, 6, 6])
In [106]: x
Out[106]:
array([[3, 3, 3],
[0, 0, 0]])
In [107]: id(y)
Out[107]: 2876795264