我有三个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
但这不起作用......
提前致谢!
答案 0 :(得分:5)
如果您对阵列的排序没有保证,那么使用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])
答案 1 :(得分: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]
原始不正确的答案
执行此操作的一种方法是使用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 :(得分: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)
此布尔掩码对应于您要替换的条目。
此解决方案的时间和空间复杂性非常糟糕:Θ( nm )替换 n 大小的数组中的 m 条目由于大布尔掩码。对于您的特定用例,我不建议使用in1d
,但它会显示在相关情况下有用的绕道。
答案 3 :(得分:2)
一个有趣的替代解决方案是使用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])
答案 4 :(得分:0)
您现在可以使用array.put
>>> a = np.arange(5)
>>> np.put(a, [0, 2], [-44, -55])
>>> a
array([-44, 1, -55, 3, 4])