2016-10-12 42 views
0

正在試驗numpy並發現這種奇怪的行爲。 此代碼工作正常:Python 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-1元和2列?

>>> 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這樣,分配不會發生

+0

目前尚不清楚*爲什麼*您需要使用'flat'。正如下面已經回答的那樣,'flat'可能會創建一個副本,因此您的更新可能不會更改原始數組。解釋爲什麼你需要「平坦」,也許你可以得到一個解決方案。 – lbolla

+0

@lbolla更新了問題 – KgOfHedgehogs

+1

@ЮраМахоткин似乎你被困在['XY問題'](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)。 – Divakar

回答

1

正如其他人指出.flat可能會創建一個原始矢量的副本,所以它的任何更新都將丟失。但flat tening一維切片是好的,所以你可以使用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是不夠的(也可能更有效)。

+0

它是循環解決我的問題的唯一方法嗎? – KgOfHedgehogs

+0

有什麼不喜歡它? – lbolla

+0

什麼也沒有,但我正在學習numpy,並期望這種情況下的一些numpy構造 – KgOfHedgehogs

2

在第一個例子中,通過展平切片,您不會更改形狀,實際上 python Numpy不會創建新對象。所以分配到扁平切片就像分配給實際切片一樣。但通過展平一個二維數組,你正在改變形狀,因此numpy製作了一個副本。

你也不必彙整片要添加到它:

In [5]: a[:, [0, 2]] += 100 

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

這個例子來自其他問題,必須使用'flat'。你能解釋如何處理'扁平'嗎? – KgOfHedgehogs

+0

@ЮраМахоткин請將用例添加到問題中,這很難回答。 – Kasramvd

0

你可以只取出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]]) 

但是你說有必要...無論您試圖添加到初始數組而不是使用flat,您都不能使用reshape嗎?

第二索引調用使該陣列的一個副本,而第一返回到它的引用:

>>> 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馬納在迭代中的元素是不相鄰的numpy的品牌一個迭代器在數組的副本上。