【问题标题】:numpy array sliced twicenumpy 数组切片两次
【发布时间】:2015-08-18 03:24:34
【问题描述】:

我不确定我是否理解为什么这不起作用:

a = np.zeros((10, ))

# first slicing array
pos1 = np.zeros((10, ), dtype=np.bool)
pos1[::2] = True

a[pos1] = 1.
print a
# returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]


# second slicing array
pos2 = np.zeros((5, ), dtype=np.bool)
pos2[::2] = True

a[pos1][pos2] = 2.

print a
# still returns [ 1.  0.  1.  0.  1.  0.  1.  0.  1.  0.]

为什么第二次切片不影响整个数组? 我以为a[pos1] 只是原始数组子部分的“视图”......我错过了什么吗?

(这个例子只是一个简单的例子,没有实际用处,只是为了尝试理解,因为我经常使用这种语法,没想到会出现这个结果)

【问题讨论】:

  • 可能与它是一项任务有关,......在左侧。
  • 只看它,您似乎正在尝试将值分配给二维数组的子集。在分配期间,it 不得从 a[pos1] 创建临时数组。您必须深入研究文档甚至源代码才能找到答案。
  • 布尔索引是"advanced indexing"的一种;这与切片不同,并且不提供原始数组的视图。

标签: python arrays numpy slice


【解决方案1】:

和最近Numpy doesn't change value of an array element after masking的问题一样

您使用的是布尔掩码,所以a[pos1] 是一个副本,而不是一个切片。

第一组有效,因为它直接调用__setitem__

a[pos1] = 1.
a.__setitem__(pos1) = 1

第二个不因为set适用于a[pos1],一个副本:

a[pos1][pos2] = 2.
a.__getitem__(pos1).__setitem__(pos2)

a[::2][pos2]=3 确实有效,因为 a[::2] 是一个切片 - 即使它产生与 a[pos1] 相同的值。

检查某个东西是副本还是视图的一种方法是查看数组的数据指针

 a.__array_interface__['data']
 a[pos1].__array_interface__['data'] # will be different
 a[::2].__array_interface__['data']  # should be the same

【讨论】:

  • 谢谢!抱歉重复,我没有找到这个问题/答案......确实是同样的问题! :)
【解决方案2】:

看一下我们定义以下三个函数时的python字节码(dis的输出):

In [187]: def b():
    a[pos1][pos2]=2
    return a

In [188]: dis.dis(b)
  2           0 LOAD_CONST               1 (2)
              3 LOAD_GLOBAL              0 (a)
              6 LOAD_GLOBAL              1 (pos1)
              9 BINARY_SUBSCR       
             10 LOAD_GLOBAL              2 (pos2)
             13 STORE_SUBSCR        

  3          14 LOAD_GLOBAL              0 (a)
             17 RETURN_VALUE        

In [189]: b()
Out[189]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [190]: def c():
    e=a.copy()
    e[pos1][pos2]=2
    return e

In [191]: dis.dis(c)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_ATTR                1 (copy)
              6 CALL_FUNCTION            0
              9 STORE_FAST               0 (e)

  3          12 LOAD_CONST               1 (2)
             15 LOAD_FAST                0 (e)
             18 LOAD_GLOBAL              2 (pos1)
             21 BINARY_SUBSCR       
             22 LOAD_GLOBAL              3 (pos2)
             25 STORE_SUBSCR        

  4          26 LOAD_FAST                0 (e)
             29 RETURN_VALUE 

In [191]: c()
Out[191]: array([ 1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.,  1.,  0.])




In [192]: def d():
    f=a[pos1]
    f[pos2]=2
    return f

In [193]: dis.dis(d)
  2           0 LOAD_GLOBAL              0 (a)
              3 LOAD_GLOBAL              1 (pos1)
              6 BINARY_SUBSCR       
              7 STORE_FAST               0 (f)

  3          10 LOAD_CONST               1 (2)
             13 LOAD_FAST                0 (f)
             16 LOAD_GLOBAL              2 (pos2)
             19 STORE_SUBSCR        

  4          20 LOAD_FAST                0 (f)
             23 RETURN_VALUE  

In [194]: d()
Out[194]: array([ 2.,  1.,  2.,  1.,  2.])

从反汇编代码来看,每次执行a[pos1][pos2]=2 赋值时,它确实存储在堆栈顶部,但随后返回的是全局(情况1)或本地(情况2)变量。 当您拆分操作时(案例 3),解释器似乎突然想起它刚刚将值存储在堆栈中并且不需要重新加载它。

【讨论】:

  • 函数d() 也不起作用...这是因为您返回了f = a[pos1] 而不是a。如果您打印a,它仍然没有任何2.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-12-11
  • 2011-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 2021-12-28
相关资源
最近更新 更多