Python numpy数组整数索引平面切片赋值

时间:2016-10-12 09:36:57

标签: python arrays python-2.7 numpy slice

正在尝试numpy并发现了这种奇怪的行为。 这段代码工作正常:

>>> a = np.array([[1, 2, 3], [4, 5, 6]])    
>>> a[:, 1].flat[:] = np.array([-1, -1])
>>> a 
array([[ 1, -1,  3],
       [ 4, -1,  6]])

但为什么这段代码不能改为0和2列的-1元素?

>>> a[:, [0, 2]].flat[:] = np.array([-1, -1])
>>> a 
array([[ 1, -1,  3],
       [ 4, -1,  6]])

如何编写代码以便更改为0和2列的-1元素?

UPD:在我的例子中使用flat或类似的smt

UPD2:我基于这段代码提出了有问题的例子:

img = imread(img_name)
xor_mask = np.zeros_like(img, dtype=np.bool)
# msg_bits looks like array([ True, False, False, ..., False, False,  True], dtype=bool)
xor_mask[:, :, channel].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)

在使用channel == 0或1或2代码分配到xor掩码后,代码工作正常,但如果channel == [1,2]或smt像这样,则不会进行赋值

3 个答案:

答案 0 :(得分:2)

在第一个示例中,通过展平切片,您不会改变形状,实际上 python Numpy不会创建新对象。因此,分配扁平切片就像分配给实际切片一样。但是通过展平二维阵列,你可以改变形状,因此numpy会复制它。

您也不需要将切片展平以添加到其中:

In [5]: a[:, [0, 2]] += 100

In [6]: a
Out[6]: 
array([[101,   2, 103],
       [104,   5, 106]])

答案 1 :(得分:1)

正如其他人所指出的,.flat可能会创建原始向量的副本,因此对它的任何更新都将丢失。但是{1}可以使用1D切片,因此您可以使用flat循环来更新多个索引。

for

请注意,您无需使用import numpy as np a = np.array([[1, 2, 3], [4, 5, 6]]) a[:, 1].flat = np.array([-1, -1]) print a # Use for loop to avoid copies for idx in [0, 2]: a[:, idx].flat = np.array([-1, -1]) print a :只需flat[:]即可(并且效率更高)。

答案 2 :(得分:0)

您可以删除flat[:] from a[:, [0, 2]].flat[:] += 100

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> a[:, 1].flat[:] += 100
>>> a
array([[  1, 102,   3],
       [  4, 105,   6]])
>>> a[:, [0, 2]] += 100
>>> a
array([[101, 102, 103],
       [104, 105, 106]])

但是你说这是必要的......不管你想要添加到初始数组而不是使用flat,你只能reshape吗?

第二个索引调用会生成数组的副本,而第一个返回对它的引用:

>>> import numpy as np
>>> a = np.array([[1, 2, 3], [4, 5, 6]])
>>> b = a[:,1].flat
>>> b[0] += 100
>>> a
array([[  1, 102,   3],
       [  4,   5,   6]])
>>> b =a[:,[0,2]].flat
>>> b[0]
1
>>> b[0] += 100
>>> a
array([[  1, 102,   3],
       [  4,   5,   6]])
>>> b[:]
array([101,   3,   4,   6])

当你希望在flat maner中迭代的元素不相邻时,numpy会在数组的副本上创建一个迭代器。