我对python不是很熟悉。我读过“数据分析用Python”这本书。最近,我对numpy布尔索引和设置有点困惑。 书上说:
通过布尔索引从数组中选择数据总是会创建数据的副本,即使返回的数组未更改。
使用布尔数组设置值以常识方式工作。
我已尝试过以下代码:
首先:
data = np.random.randn(7, 4)
data[data < 0] = 0 # this could change the `data`
第二
data = np.random.randn(7, 4)
copied = data[data < 0]
copied[1] = 1 # this couldn't change the `data`
我在这里不太明白,任何人都可以解释。根据我的理解,copied
应该是指向数据的指针[data&lt; 0]切片。
答案 0 :(得分:2)
虽然data[data < 0] = 0
sorta看起来像是设置为0
的视图,但这不是实际发生的事情。实际上,ndarray
后跟=
来电__setitem__
来处理分段分配。
当ndarray位于=
的另一侧时,__setitem__
未被调用,并且您指定了一个副本(如布尔索引总是这样),它独立于原始数组。 / p>
本质:
foo[foo != bar] = bar # calls __setitem__
foo[:2] = bar # calls __setitem__
bar = foo[foo != bar] # makes a copy
bar = foo[:2] # makes a view
答案 1 :(得分:2)
根据经验,numpy会尽可能创建视图,并在必要时创建副本。
何时可以查看?当可以使用步幅来寻址数据时,即例如对于2d阵列A,每个A[i, j]
位于地址base + i*stride[0] + j*stride[1]
的存储器中。如果您仅使用切片创建一个子阵列,那么这将是您获得视图的原因。
对于逻辑和高级索引,通常无法找到恰好解决正确元素的基础和步幅。因此,这些操作返回一个复制了数据的新数组。
答案 2 :(得分:0)
基于代码序列:
data = np.random.randn(7, 4)
:Thi step创建一个大小为7乘4的数组data[data < 0] = 0
:使数据中的所有元素都是&lt; 0为0 copied = data[data < 0]
:此步骤生成一个空数组,因为数据中没有&lt; 0,因为步骤4 copied[1] = 1
:此步骤引发错误,因为复制是一个空数组,因此索引1不存在