Python numpy 数组整数索引平面切片赋值
Python numpy array integer indexed flat slice assignment
正在试验 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)
并且在分配给通道 == 0 或 1 或 2 代码的异或掩码后工作正常,但如果通道 == [1,2] 或像这样的 smt,分配不会发生
在第一个示例中,通过展平切片不会改变形状,实际上 python Numpy 不会创建新对象。所以分配给扁平切片就像分配给实际切片一样。但是通过展平一个二维数组,你改变了形状,因此 numpy 复制了它。
此外,您无需展平切片即可添加:
In [5]: a[:, [0, 2]] += 100
In [6]: a
Out[6]:
array([[101, 2, 103],
[104, 5, 106]])
您可以删除 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]])
但是你说这是必要的......你不能只 reshape
任何你想添加到初始数组而不是使用 flat
的东西吗?
第二个索引调用复制数组,而第一个 returns 引用它:
>>> 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 会在数组的副本上进行迭代。
正如其他人指出的那样,.flat
可能会创建原始矢量的副本,因此对其进行的任何更新都将丢失。但是 flat
tening 一个 1D 切片很好,所以你可以使用 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[:]
:只需 flat
就足够了(而且效率可能更高)。
正在试验 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)
并且在分配给通道 == 0 或 1 或 2 代码的异或掩码后工作正常,但如果通道 == [1,2] 或像这样的 smt,分配不会发生
在第一个示例中,通过展平切片不会改变形状,实际上 python Numpy 不会创建新对象。所以分配给扁平切片就像分配给实际切片一样。但是通过展平一个二维数组,你改变了形状,因此 numpy 复制了它。
此外,您无需展平切片即可添加:
In [5]: a[:, [0, 2]] += 100
In [6]: a
Out[6]:
array([[101, 2, 103],
[104, 5, 106]])
您可以删除 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]])
但是你说这是必要的......你不能只 reshape
任何你想添加到初始数组而不是使用 flat
的东西吗?
第二个索引调用复制数组,而第一个 returns 引用它:
>>> 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 会在数组的副本上进行迭代。
正如其他人指出的那样,.flat
可能会创建原始矢量的副本,因此对其进行的任何更新都将丢失。但是 flat
tening 一个 1D 切片很好,所以你可以使用 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[:]
:只需 flat
就足够了(而且效率可能更高)。