2013-12-18 56 views
2

修改多個元素我有三個numpy的數組:numpy的陣列一次

row = np.array([1,2,3,4,5]) 

# a is a subset of row: 

a = np.array([1, 5]) 

# b is an array that I use to change some elements in the first row array: 

b = np.array([10, 550]) 

我需要做的是改變一次性所存在的排陣的元素在與記者b元素。

即:

>> modified_row 
array([10, 2, 3, 4, 500]) 

以簡單的方式進行,這將是:

for i in range(len(a)): 
    row[np.where(row==a[i])]= b[i] 

我想一個解決方案等;

row[np.where(row==a)] = b 

但是,這並不工作...

提前感謝!

+0

您能說明您對重複元素的預期行爲嗎? – wim

+0

@wim,事實是,對於我的問題,所有元素都是唯一的,排序不是問題,因爲這些值本身就是索引。 – BangTheBank

回答

4

請注意@ Jaime的答案更好 - 儘管它依賴於元素的排序,但它被標記爲正確。這是一個工作版本,不會在原地修改row,否則將在一般情況下工作。在這篇文章的最後是我的原始答案。

import numpy as np 

def replaced(row, a, b): 
    row_order = row.argsort() 
    a_order = a.argsort() 

    sorted_row = row[row_order] 
    sorted_a = a[a_order] 
    sorted_b = b[a_order] 

    sorted_row[np.in1d(sorted_row, sorted_a)] = sorted_b 

    # return results in original order 
    return sorted_row[row_order.argsort()] 

a = np.array([1, 5]) 
b = np.array([10, 550]) 

row = np.array([1,2,3,4,5]) 
print replaced(row, a, b) 

row = np.array([5,4,3,2,1]) 
print replaced(row, a, b) 

row = np.array([4, 5, 1, 3, 2]) 
print replaced(row, a, b) 

結果:

>>> row = np.array([1,2,3,4,5]) 
>>> print replaced(row, a, b) 
[ 10 2 3 4 550] 
>>> 
>>> row = np.array([5,4,3,2,1]) 
>>> print replaced(row, a, b) 
[550 4 3 2 10] 
>>> 
>>> row = np.array([4, 5, 1, 3, 2]) 
>>> print replaced(row, a, b) 
[ 4 550 10 3 2] 

ORIGINAL不正確的答案要做到這一點

的一種方法是用in1d功能,這將產生一個布爾數組,您可以使用索引row爲如下所示。

注意,你可能有這個問題(以及其他方法)如果row元素不是唯一的,或者如果你已經在a

>>> import numpy as np 
>>> row = np.array([1,2,3,4,5]) 
>>> a = np.array([1, 5]) 
>>> b = np.array([10, 550]) 
>>> np.in1d(row, a) 
array([ True, False, False, False, True], dtype=bool) 
>>> row[np.in1d(row, a)] = b 
>>> row 
array([ 10, 2, 3, 4, 550]) 

重複的元素就可以正常使用任何索引/布爾數組你最初用於提取a也爲此目的。

+2

你假設所有的數組都是排序的,你的解決方案對'a = [5,1]'無法正常工作,因爲它會將來自'b'的值放在錯誤的位置。 – Jaime

+0

@Jaime你說得對 - OP你應該從這篇文章中刪除接受的標誌。 – YXD

+0

np.in1d會用一些小心的參數來工作,但我沒有時間在這一刻改正它 – YXD

1

一個有趣的替代解決方案是使用numpy.put作爲記錄here。在這種情況下,仔細考慮如果row中有重複項會發生什麼也很重要。默認情況下,如果在這種情況下有兩個以上的匹配,put將循環遍歷b中的元素。

import numpy as np 
row = np.array([1,2,3,4,5]) 
a = np.array([1, 5]) 
b = np.array([10, 550]) 
index_list = [np.where(row == element) for element in a] 
np.put(row,index_list,b) 
row 
array([ 10, 2, 3, 4, 550]) #output 

編輯:額外的例子來應對意見基於索引的分配查詢:

>>> import numpy as np 
>>> target_array = np.arange(50) 
>>> n = 2 
>>> index_array = np.arange(0,len(target_array),n) 
>>> b = np.array([10, 550]) 
>>> np.put(target_array, index_array, b) 
>>> target_array #note that np.put cycles through the substitutions in b 
array([ 10, 1, 550, 3, 10, 5, 550, 7, 10, 9, 550, 11, 10, 
     13, 550, 15, 10, 17, 550, 19, 10, 21, 550, 23, 10, 25, 
     550, 27, 10, 29, 550, 31, 10, 33, 550, 35, 10, 37, 550, 
     39, 10, 41, 550, 43, 10, 45, 550, 47, 10, 49]) 
+0

如果我們想改變給定n的倍數的索引值,比如[2],我們該怎麼做, ,a [4],a [6],a [8] ..... for n = 2? –

+1

我已經爲此添加了一個示例。 – treddy

+0

好的,我明白了! –

3

另一種可能性:

>>> row = np.array([1,2,3,4,5]) 
>>> row[np.any(row.reshape(-1, 1) == a, axis=1)] = b 
>>> row 
array([ 10, 2, 3, 4, 550]) 

其工作原理是:

>>> row.reshape(-1, 1) == a 
array([[ True, False], 
     [False, False], 
     [False, False], 
     [False, False], 
     [False, True]], dtype=bool) 
>>> np.any(row.reshape(-1, 1) == a, axis=1) 
array([ True, False, False, False, True], dtype=bool) 

而這個b oolean掩碼對應於您要替換的條目。

該溶液的時間和空間複雜度是相當差:Θ(納米)取代條目大小Ñ的陣列由於大的布爾掩碼。我不推薦使用in1d作爲您的特定用例,但它顯示了在相關案例中很有用的繞道。

+0

是的,這些中間結果絕對有用。儘管如此,我會建議將它寫爲'np.any(row [...,None] == a,axis = 1)'。總是需要更長時間才能瞭解重塑操作與顯式廣播。 – YXD

+1

@MrE:我想這是一個品味問題;我習慣scikit-learn codebase,其中'reshape(-1,1)'是轉置一維數組的常用方法。但'np.any'是個好主意,我應該自己想到這個。 –

+0

如果我們想要改變給定n的倍數的索引值,比如[2],a [4],a [6],a [8] ...... n = 2 ? –

4

如果你沒有對你的數組排序保證,你可以有使用np.searchsorted一個合理有效的實現:

def find_and_replace(array, find, replace): 
    sort_idx = np.argsort(array) 
    where_ = np.take(sort_idx, 
        np.searchsorted(array, find, sorter=sort_idx)) 
    if not np.all(array[where_] == find): 
     raise ValueError('All items in find must be in array') 
    row[where_] = b 

,這不能處理重複在array項中的唯一的事情,但除此之外,它的作用就像是一種魅力:

>>> row = np.array([5,4,3,2,1]) 
>>> a = np.array([5, 1]) 
>>> b = np.array([10, 550]) 
>>> find_and_replace(row, a, b) 
>>> row 
array([ 10, 4, 3, 2, 550]) 

>>> row = np.array([5,4,3,2,1]) 
>>> a = np.array([1, 5]) 
>>> b = np.array([10, 550]) 
>>> find_and_replace(row, a, b) 
>>> row 
array([550, 4, 3, 2, 10]) 

>>> row = np.array([4, 5, 1, 3, 2]) 
>>> find_and_replace(row, a, b) 
>>> row 
array([ 4, 550, 10, 3, 2]) 
+0

如果我們想要改變給定n的倍數的索引值,如[2],a [4],a [6],a [8] ..... n = 2 ? –