我想用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它的大小作为最高尺寸相同一个。
In[]: b.shape
Out[]: (101,)
我想减去b从一个以这样的方式使得ン在第元件b被从值中减去一个[NN,...,0] 。我知道我可以使用for循环来做到这一点,但是也应该可以广播b,这样我可以使用类似
In[]: c= a[:,...,0]-b[somehow broadcastet or reshaped]
In[]: c.shape()
Out[]: (101, 256, 1, 3, 1, 10)
您确实可以利用广播来做到这一点。
让我们首先生成一些ndarrays
指定形状的随机数,以检查最终尺寸是否符合预期:
a = np.random.rand(101, 256, 1, 3, 1, 10)
b = np.random.rand(101)
在这种情况下,您必须将的a.ndim
尺寸加起来,b
以便将中的每个值b
减去的最后一个尺寸中的每个值a
。继从构思这个文章中,我们最多可以添加a.ndim
使用一种更简洁的方式新dimensionsionsnp.reshape
如下:
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[:,0,None] - b
array([[0],
[3]])
这样我们可以获得正确的输出。
使用上述方法,似乎不可能将差异分配给充当a的“校正副本”的新数组?
通过查看减法的结果,可以理解该问题的答案:
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
。如果确实要保存原始副本,则ndarray
可以使用np.copy
,它将返回实际副本,而不是的一部分a
,然后将结果分配给“更正副本”:
a_c = np.copy(a)
a_c[:,0,None] = a[:,0,None] - b
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句