簡體   English   中英

Numpy數組一次修改多個元素

[英]Numpy array modifying multiple elements at once

我有三個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])

我需要做的是一次性改變a對應的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

但這不起作用......

提前致謝!

如果您對陣列的排序沒有保證,那么使用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])

請注意@ 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]

原始的不正確的答案

一種方法是使用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任何索引/布爾數組來實現此目的。

另一種可能性

>>> 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)

此布爾掩碼對應於要替換的條目。

此解決方案的時間和空間復雜性非常糟糕:由於布爾掩碼較大,Θ( nm )將替換大小為n的數組中的m個條目。 對於您的特定用例,我不建議使用in1d ,但是它顯示了在相關情況下有用的繞道。

一個有趣的替代解決方案是使用numpy.put作為記錄在這里 在這種情況下,仔細考慮如果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])

您現在可以使用array.put

>>> a = np.arange(5)
>>> np.put(a, [0, 2], [-44, -55])
>>> a
array([-44,   1, -55,   3,   4])

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM