我想用b [nn]减去a [nn,...,0]中的所有值,而 保持数组 a 的原始结构。
我从ndnumpy数组进行索引和逐元素减法时遇到问题。 就我而言,数组 a 具有6个维度
In[]: a.shape
Out[]: (101, 256, 1, 3, 1, 10)
出于一致性考虑,最小维度 N = 0 具有10个元素,最大维度 N = 5 具有101个元素。
我还有一个一维数组 b ,它的大小与最大 a 中的尺寸。
In[]: b.shape
Out[]: (101,)
我想从 a 中减去 b ,使 b 中的第 nn 个元素是 从值 a [nn,...,0] 中减去。我知道我可以使用for循环来做到这一点,但是也应该可以广播 b ,这样我可以使用类似
的东西In[]: c= a[:,...,0]-b[somehow broadcastet or reshaped]
In[]: c.shape()
Out[]: (101, 256, 1, 3, 1, 10)
答案 0 :(得分:1)
您确实可以利用broadcasting来做到这一点。
让我们先生成一些指定形状的随机ndarrays
以便检查最终尺寸是否符合预期:
a = np.random.rand(101, 256, 1, 3, 1, 10)
b = np.random.rand(101)
在这种情况下,您必须向a.ndim
添加多达b
个维度,以便将b
中的每个值减去{{1}的最后一个维度中的每个值}}。遵循this帖子中的想法,我们可以使用np.reshape
以更简洁的方式添加多达a
个新尺寸,如下所示:
a.ndim
现在我们可以根据需要从b = b.reshape((-1,) + (1,)*(a.ndim-1))
print(b.shape)
# (101, 1, 1, 1, 1, 1)
中减去b
,
a
如果我们检查a[..., 0, None] = a[..., 0, None] - b.reshape((-1,) + (1,) * (a.ndim-1))
的形状:
a
以下是一些有关先前答案可能引起的问题的说明。让我们考虑以下更简单的示例:
print(a.shape)
# (101, 256, 1, 3, 1, 10)
因此,在此示例中,我们可以使用与上述解决方案相同的逻辑:
a = np.array([[1,2,3],[4,5,6]])
print(a)
array([[1, 2, 3],
[4, 5, 6]])
print(a.shape)
# (2, 3)
b = np.array([1,1])[:,None]
array([[1],
[1]])
print(b.shape)
# (2, 1)
通过检查结果数组,如预期的那样,a[:,0,None] = a[:,0,None] - b
array([[0, 2, 3],
[3, 5, 6]])
已从沿其最后一条轴的第一个索引的b
中减去,因此所有行的第一列。
第一点,
为什么我们必须在
a
中添加新轴才能进行减法?
给定a
的形状,有必要向a
添加新轴。请注意,b
是二维数组b
,因此,如果直接从array([[1],[1]])
中减去它,则会得到:
a
因此,这里发生的是较小的数组,即第一项,它只是a[..., 0] - b
array([[0, 3],
[0, 3]])
,1D
中的a
视图切片,已在较大的数组中广播数组,以便它们具有兼容的形状。
如果array([1, 4])
的形状改为b
,则不必这样做:
(2,)
但是,由于在实际解决方案中定义了b = np.array([1,1])
a[:,0] - b
# array([0, 3])
的方式,其尺寸与b
相同。因此,为了获得正确的输出,我们必须向a
添加一个新轴:
a
这样,我们可以获得正确的输出。
使用上述方法,似乎不可能将差异分配给充当a的“校正副本”的新数组?
通过查看减法的结果可以理解这个问题的答案:
a[:,0,None] - b
array([[0],
[3]])
因此,c = a[:,0,None] - b
c.shape
(2, 1)
在这里是a[:,0,None]
的“切片视图”。因此请注意,通过将此结果分配给a
,您只保存了c
的实际sliced wiew
,而不是整个a
。如果要在实际切片的相同位置上修改ndarray
,则必须将其分配给a
的相同切片视图,因此:
a
现在,由于仅修改了a[:,0,None] = a[:,0,None] - b
print(a.shape)
# (2, 3)
的一部分,因此结果确实具有预期的输出。如果您确实想保存原始a
的副本,则可以使用np.copy
,它将返回实际的副本而不是ndarray
的一部分,然后将结果分配给“更正的副本”:
a