在NumPy数组中用另一个数组中最接近的值替换元素

4
给定两个不同大小的数组 aabb,我需要用 bb 中最接近的元素替换 aa 中的元素。
这是我目前有的。它可以正常工作,但我想知道是否有更好的方法。
import numpy as np

# Some random data
aa = np.random.uniform(0., 1., 100)
bb = np.array([.1, .2, .4, .55, .97])

# For each element in aa, find the index of the nearest element in bb
idx = np.searchsorted(bb, aa)
# For indexes to the right of the rightmost bb element, associate to the last
# bb element.
msk = idx > len(bb) - 1
idx[msk] = len(bb) - 1

# Replace values in aa
aa = np.array([bb[_] for _ in idx])


[*]:实际上它 几乎 可以使用。正如评论中指出的那样,np.searchsorted 并不返回最接近元素的索引,而是返回 "已排序数组 a 的索引,使得如果在这些索引之前插入相应的 v 中的元素,则 a 的顺序将被保留",这并不相同。


1
searchsorted 无法找到最近的元素 - 您仍然需要检查两个候选项以确定哪一个更接近。 - user2357112
这是一个很好的观点,我之前并没有真正考虑过。 - Gabriel
2个回答

5
你需要计算 aabb 中每个元素之间的差值,并取最小值:
aa_nearest = bb[abs(aa[None, :] - bb[:, None]).argmin(axis=0)]

很棒的答案,简单又快速。谢谢Daniel! - Gabriel
请注意,对于小数组来说速度非常快,但对于较大的数组来说速度会非常慢。 - DSM
@DSM:哪个更快? - Daniel
在我的测试中,即使对于aa中的一百万个元素,在我那古老的笔记本电脑上也只需要不到1秒钟的时间。而Abhinav的答案则需要超过11秒钟的时间。 - Gabriel
当 aa 和 bb 都较大时,性能问题就会出现,因为我们正在创建一个大小为 aa * bb 的中间数组。只要您知道 bb 的最大大小很小,您就不会有问题。 - DSM

0
毫无疑问,Daniel的答案令人印象深刻,但对于大型数组来说可能会很慢,因为计算和比较的数量将会很高。
另一种实现方法是:
import numpy as np
aa = np.random.uniform(0., 1., 100)
bb = np.array([.1, .2, .4, .55, .97])
idx = np.searchsorted(bb, aa)
msk = idx > len(bb) - 1
idx[msk] = len(bb) - 1

idx_new=np.array([idx[i]-1 if abs(bb[idx[i]-1]-aa[i])<abs(bb[idx[i]]-aa[i]) else idx[i] for i in range(len(idx))])
aa = np.array([bb[_] for _ in idx_new])

这里使用searchsorted()函数后,仅计算相邻值之间的差异。


1
使用索引和for循环比矩阵操作慢得多。 - Daniel
1
请看我在另一个答案中的评论,这比丹尼尔的方法慢得多。 - Gabriel
在提到性能时,你至少应该对代码进行计时。 - user3483203
好的,谢谢,我明白了。我只是认为从算法上来看它的操作次数较少,但条件语句需要时间,也许我应该使用其他方法来应用相同的算法。 - Abhinav Mishra

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接