【问题标题】:Python numpy array integer indexed flat slice assignmentPython numpy 数组整数索引平面切片分配
【发布时间】:2017-02-21 01:28:04
【问题描述】:

正在试验 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 代码分配给 xor 掩码后可以正常工作,但如果通道 == [1,2] 或像这样的 smt,则不会发生分配

【问题讨论】:

  • 不清楚为什么你需要使用flat。正如下面已经回答的那样,flat 可能会创建一个副本,因此您的更新可能不会更改原始数组。解释为什么你需要flat,也许你能找到解决方案。
  • @lbolla 更新问题
  • @ЮраМахоткин 看来你被困在XY problem 中了。
  • @Divakar 是的,你说得对。我将再次发布问题,但问题表述正确

标签: python arrays python-2.7 numpy slice


【解决方案1】:

正如其他人指出的那样,.flat 可能会创建原始向量的副本,因此对其进行的任何更新都会丢失。但是flattening 一维切片很好,因此您可以使用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 并希望针对这种情况进行一些 numpy 构造
  • 好吧,您似乎已确定使用flat,但flat 必须根据您的情况创建副本,因此无法使用。我认为你只需要“调整”你的期望......
  • 但是等等。 For-loop 不符合我的需求:xor_mask[:, :, channel].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool)for ch in channel: xor_mask[:, :, ch].flat[:len(msg_bits)] = np.ones_like(msg_bits, dtype=np.bool) 在逻辑上做了不同的处理
  • 你必须相应地打破msg_bits。我不知道你为什么执着于使用flat,所以我无法给你一个有意义的建议。
【解决方案2】:

您可以删除 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 吗?

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

>>> 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 会在数组的副本上生成一个迭代器。

【讨论】:

    【解决方案3】:

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

    你也不需要展平你的切片来添加它:

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

    【讨论】:

    • 这个例子来自其他问题,有必要使用flat。你能解释一下如何处理flat吗?
    • @ЮраМахоткин 请把用例添加到问题中,这样很难回答。
    猜你喜欢
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-11
    相关资源
    最近更新 更多