2016-09-29 125 views
3

当使用numpy的命名阵列我观察在以下两种情况下不同的行为:意外行为

  1. 情况下:首先使用用于高级切片索引阵列,然后通过选择一个子阵列命名
  2. 情况下:第一选择由名称的子阵列,然后使用先进的索引阵列切片

的follwing代码提出的实施例

import numpy as np 

a = np.ones(5) 
data = np.array(zip(a, a, a), dtype=[("x", float), ("y", float), ("z", float)]) 

# case 1 
# does not set elements 1, 3 and 4 of data to 22 
data[[1, 3, 4]]["y"] = 22  
print data["y"] # -> [ 1. 1. 1. 1. 1.] 

# case 2 
# set elements 1, 3 and 4 of data to 22 
data["y"][[1, 3, 4]] = 22 
print data["y"] # -> [ 1. 22. 1. 22. 22.] 

两个打印命令的输出是 [1.1.1.1.1]和[1.22.1 22. 22.]。为什么在设置元素时改变选择的顺序会导致不同的结果?

回答

3

索引与列表或阵列always returns a copy rather than a view

In [1]: np.may_share_memory(data, data[[1, 3, 4]]) 
Out[1]: False 

因此分配data[[1, 3, 4]]["y"] = 22被修改拷贝的data[[1, 3, 4]],并且在data原始值不会受到影响。

在另一方面,参照结构化阵列returns a view的字段:

In [2]: np.may_share_memory(data, data["y"]) 
Out[2]: True 

所以分配给data["y"][[1, 3, 4]]影响data的相应的元件。

+0

正如你所说的用列表或数组索引总是返回一个副本而不是视图。这解释了为什么data [[1,3,4]] [“y”] = 22'正在处理'data'的副本。但出于同样的原因,data [“y”] [[1,3,4]]只应该在data [“y”]的副本上工作。这也显示了'np.may_share_memory(data,data [“y”] [[1,3,4]])',它变成了'False'。所以我不明白为什么这个排序工作。 – murban

+0

可以使用索引表达式来分配元素,只要您直接执行分配,而不会链接任何其他索引操作,索引表达式就会返回副本。例如,'x [[1,2,3]] = 4,5,6'将起作用,但'x [[1,2,3]] [:] = 4,5,6'不会影响'因为第一个索引表达式返回一个副本。 –