繁体   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