为什么我不能用单列矩阵替换 NumPy 数组中的列?
Why i cannot replace a column in NumPy array by a single-column matrix?
我遇到了 NumPy 数组的奇怪行为。我正在处理一些矩阵代数示例,我发现您可以轻松地将数组列(或一行)替换为各种类型的数据,但不能替换为具有正确行数和单列数的数组。
让我们有一个数组:
>>> import numpy as np
>>>
>>> A = np.zeros([4,4])
>>> A
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
现在让我们给rows/columns赋一些值:
>>> A[0,:] = [1,1,1,1]
>>> A
array([[1., 1., 1., 1.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>>
>>> A[:,0] = np.array([2,2,2,2])
>>> A
array([[2., 1., 1., 1.],
[2., 0., 0., 0.],
[2., 0., 0., 0.],
[2., 0., 0., 0.]])
>>>
>>> A[2,:] = np.array([[3,3,3,3]])
>>> A
array([[2., 1., 1., 1.],
[2., 0., 0., 0.],
[3., 3., 3., 3.],
[2., 0., 0., 0.]])
>>>
>>> A[:,2] = np.array([[4,4,4,4]])
>>> A
array([[2., 1., 4., 1.],
[2., 0., 4., 0.],
[3., 3., 4., 3.],
[2., 0., 4., 0.]])
在最后两个替换中,我分配了一个 1x4 数组作为新行,并分配了一个 1x4 数组作为新列。
但是由于我不知道的原因,我无法将 4x1 数组分配给现有数组的列或行:
>>> A[:,3] = np.array([[5],[5],[5],[5]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (4,1) into shape (4,)
我用谷歌搜索了这个错误,我仍然认为这可能是一个设计缺陷。
是否有实际原因不允许将 Nx1
数组作为列分配给 NxM
数组?
需要广播,使用:
>>> A
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> A[:,3:4] = np.array([[5],[5],[5],[5]])
>>> A
array([[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.]])
A[:, 3]
的形状是 (n,)
,即 1-D array
,而 A[:, 3:4]
的形状是 (n, 1)
,这与你的数组相同正在尝试分配。
>>> A[:, 3]
array([0., 0., 0., 0.])
>>> A[:, 3].shape
(4, )
>>> A[:, 3:4]
array([[0.],
[0.],
[0.],
[0.]])
>>> A[:, 3:4].shape
(4, 1)
不同的是,3
只是一个整数,而不是一个索引,3:4
是一个slice
对象,slice(3, 4, None)
,你可以这样想例如,您正在沿轴 1 切割一部分,而不是只选择一个索引。
编辑:
或者,您可以在列表中沿轴 1 传递索引:
>>> A[:, [3]] = np.array([[5],[5],[5],[5]])
>>> A
array([[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.]])
要查看更多信息,请查看 Broadcasting Rules
作为已接受答案的附录:
创建 2 个数组,一个 1d,另一个 2d(但元素数量相同):
In [73]: x = np.ones((4,),int); y = np.ones((4,1),int)*10
In [74]: x
Out[74]: array([1, 1, 1, 1])
In [75]: y
Out[75]:
array([[10],
[10],
[10],
[10]])
当我们添加它们时,我们得到 (4,4) 结果:
In [76]: x+y
Out[76]:
array([[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11]])
根据广播规则,2 个数组的维数必须相同。它可以自动添加前导尺寸,将 (4,) 变为 (1,4):
In [77]: x[None,:]+y
Out[77]:
array([[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11]])
根据第 2 条规则,尺寸 1 的尺寸被调整,所以 (1,4)=>(4,4) 和 (4,1)=>(4,4),结果是 (4, 4) 数组。
通过分配,RHS 可以添加前导尺寸并调整 1。但是LHS基本没变:
In [78]: x[:] = y
Traceback (most recent call last):
File "<ipython-input-78-4f264a106454>", line 1, in <module>
x[:] = y
ValueError: could not broadcast input array from shape (4,1) into shape (4)
将 RHS 更改为 (1,4) 有效:
In [79]: x[:] = y.T
In [80]: x
Out[80]: array([10, 10, 10, 10])
或将其更改为 (4,):
In [81]: x[:] = y.ravel()
或将 LHS 更改为 (4,1):
In [83]: x[:,None] = y
已接受的答案最后有效地做到了这一点 A[:, [3]]
我本来想说 LHS 不能更改,但是将 (1,4) 分配给 (4,) 的能力让我犹豫了。将 (1,4) 分配给 (4,) 时,是将 LHS 调整为 (1,4)(自动引导尺寸),还是将 RHS (1,4) 更改为 (4,)。细节可能并不重要。关键是不能添加(或删除)尾随维度。
需要前导尺寸和尾随尺寸之间的差异以避免歧义。想象一下尝试添加 (3,) 和 (4,)。这会导致 (3,4) 或 (4,3) 吗? (3,1)+(1,4) 或 (1,3)+(4,1)。使用领先规则,您必须明确,添加 (3,1)+(4,) 或 (3,)+(4,1).
我遇到了 NumPy 数组的奇怪行为。我正在处理一些矩阵代数示例,我发现您可以轻松地将数组列(或一行)替换为各种类型的数据,但不能替换为具有正确行数和单列数的数组。
让我们有一个数组:
>>> import numpy as np
>>>
>>> A = np.zeros([4,4])
>>> A
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
现在让我们给rows/columns赋一些值:
>>> A[0,:] = [1,1,1,1]
>>> A
array([[1., 1., 1., 1.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>>
>>> A[:,0] = np.array([2,2,2,2])
>>> A
array([[2., 1., 1., 1.],
[2., 0., 0., 0.],
[2., 0., 0., 0.],
[2., 0., 0., 0.]])
>>>
>>> A[2,:] = np.array([[3,3,3,3]])
>>> A
array([[2., 1., 1., 1.],
[2., 0., 0., 0.],
[3., 3., 3., 3.],
[2., 0., 0., 0.]])
>>>
>>> A[:,2] = np.array([[4,4,4,4]])
>>> A
array([[2., 1., 4., 1.],
[2., 0., 4., 0.],
[3., 3., 4., 3.],
[2., 0., 4., 0.]])
在最后两个替换中,我分配了一个 1x4 数组作为新行,并分配了一个 1x4 数组作为新列。 但是由于我不知道的原因,我无法将 4x1 数组分配给现有数组的列或行:
>>> A[:,3] = np.array([[5],[5],[5],[5]])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: could not broadcast input array from shape (4,1) into shape (4,)
我用谷歌搜索了这个错误,我仍然认为这可能是一个设计缺陷。
是否有实际原因不允许将 Nx1
数组作为列分配给 NxM
数组?
需要广播,使用:
>>> A
array([[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.],
[0., 0., 0., 0.]])
>>> A[:,3:4] = np.array([[5],[5],[5],[5]])
>>> A
array([[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.]])
A[:, 3]
的形状是 (n,)
,即 1-D array
,而 A[:, 3:4]
的形状是 (n, 1)
,这与你的数组相同正在尝试分配。
>>> A[:, 3]
array([0., 0., 0., 0.])
>>> A[:, 3].shape
(4, )
>>> A[:, 3:4]
array([[0.],
[0.],
[0.],
[0.]])
>>> A[:, 3:4].shape
(4, 1)
不同的是,3
只是一个整数,而不是一个索引,3:4
是一个slice
对象,slice(3, 4, None)
,你可以这样想例如,您正在沿轴 1 切割一部分,而不是只选择一个索引。
编辑:
或者,您可以在列表中沿轴 1 传递索引:
>>> A[:, [3]] = np.array([[5],[5],[5],[5]])
>>> A
array([[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.],
[0., 0., 0., 5.]])
要查看更多信息,请查看 Broadcasting Rules
作为已接受答案的附录:
创建 2 个数组,一个 1d,另一个 2d(但元素数量相同):
In [73]: x = np.ones((4,),int); y = np.ones((4,1),int)*10
In [74]: x
Out[74]: array([1, 1, 1, 1])
In [75]: y
Out[75]:
array([[10],
[10],
[10],
[10]])
当我们添加它们时,我们得到 (4,4) 结果:
In [76]: x+y
Out[76]:
array([[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11]])
根据广播规则,2 个数组的维数必须相同。它可以自动添加前导尺寸,将 (4,) 变为 (1,4):
In [77]: x[None,:]+y
Out[77]:
array([[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11],
[11, 11, 11, 11]])
根据第 2 条规则,尺寸 1 的尺寸被调整,所以 (1,4)=>(4,4) 和 (4,1)=>(4,4),结果是 (4, 4) 数组。
通过分配,RHS 可以添加前导尺寸并调整 1。但是LHS基本没变:
In [78]: x[:] = y
Traceback (most recent call last):
File "<ipython-input-78-4f264a106454>", line 1, in <module>
x[:] = y
ValueError: could not broadcast input array from shape (4,1) into shape (4)
将 RHS 更改为 (1,4) 有效:
In [79]: x[:] = y.T
In [80]: x
Out[80]: array([10, 10, 10, 10])
或将其更改为 (4,):
In [81]: x[:] = y.ravel()
或将 LHS 更改为 (4,1):
In [83]: x[:,None] = y
已接受的答案最后有效地做到了这一点 A[:, [3]]
我本来想说 LHS 不能更改,但是将 (1,4) 分配给 (4,) 的能力让我犹豫了。将 (1,4) 分配给 (4,) 时,是将 LHS 调整为 (1,4)(自动引导尺寸),还是将 RHS (1,4) 更改为 (4,)。细节可能并不重要。关键是不能添加(或删除)尾随维度。
需要前导尺寸和尾随尺寸之间的差异以避免歧义。想象一下尝试添加 (3,) 和 (4,)。这会导致 (3,4) 或 (4,3) 吗? (3,1)+(1,4) 或 (1,3)+(4,1)。使用领先规则,您必须明确,添加 (3,1)+(4,) 或 (3,)+(4,1).