系统
操作系统: Windows 10 (x64),Build 1909
Python 版本: 3.8.10
Numpy 版本: 1.21.2
问题
给定两个浮点数据点的 2D (N, 3)
Numpy 数组,(x, y, z)
在一个数组中查找点与另一个数组中的点相等的索引的 Pythonic(矢量化)方法是什么?
(注意: 我的问题不同之处在于我需要它来处理实际数据集,其中两个数据集可能因浮点错误而有所不同。请阅读下面的详细信息。)
历史
类似的问题已经被问过很多次了:
- 如何找到另一个二维数组中出现的二维numpy数组的索引
- 测试二维 numpy 数组中的成员资格
- 获取 Numpy 2d 数组相交行的索引
- 在另一个二维数组中查找 numpy 二维数组行的索引
- Numpy 2d Array 相交行的索引
- 在另一个二维数组中查找 numpy 二维数组行的索引
以前的尝试
SO Post 1提供了一个工作列表理解解决方案,但我正在寻找一种能够很好地扩展到大型数据集(即数百万点)的解决方案:
代码1:
import numpy as np
if __name__ == "__main__":
big_array = np.array(
[
[1.0, 2.0, 1.2],
[5.0, 3.0, 0.12],
[-1.0, 14.0, 0.0],
[-9.0, 0.0, 13.0],
]
)
small_array = np.array(
[
[5.0, 3.0, 0.12],
[-9.0, 0.0, 13.0],
]
)
inds = [
ndx
for ndx, barr in enumerate(big_array)
for sarr in small_array
if all(sarr == barr)
]
print(inds)
输出1:
[1, 2]
尝试SO Post 3的解决方案(类似于SO Post 2),但使用浮点数不起作用(我怀疑np.isclose
需要使用一些东西):
代码3:
import numpy as np
if __name__ == "__main__":
big_array = np.array(
[
[1.0, 2.0, 1.2],
[5.0, 3.0, 0.12],
[-1.0, 14.0, 0.0],
[-9.0, 0.0, 13.0],
],
dtype=float,
)
small_array = np.array(
[
[5.0, 3.0, 0.12],
[-9.0, 0.0, 13.0],
],
dtype=float,
)
inds = np.nonzero(
np.in1d(big_array.view("f,f").reshape(-1), small_array.view("f,f").reshape(-1))
)[0]
print(inds)
输出3:
[ 3 4 5 8 9 10 11]
我的尝试
我试过numpy.isin
和np.all
np.argwhere
inds = np.argwhere(np.all(np.isin(big_array, small_array), axis=1)).reshape(-1)
哪个有效(并且,我认为,更具可读性和可理解性;即pythonic),但不适用于包含浮点错误的真实数据集:
import numpy as np
if __name__ == "__main__":
big_array = np.array(
[
[1.0, 2.0, 1.2],
[5.0, 3.0, 0.12],
[-1.0, 14.0, 0.0],
[-9.0, 0.0, 13.0],
],
dtype=float,
)
small_array = np.array(
[
[5.0, 3.0, 0.12],
[-9.0, 0.0, 13.0],
],
dtype=float,
)
small_array_fpe = np.array(
[
[5.0 + 1e-9, 3.0 + 1e-9, 0.12 + 1e-9],
[-9.0 + 1e-9, 0.0 + 1e-9, 13.0 + 1e-9],
],
dtype=float,
)
inds_no_fpe = np.argwhere(np.all(np.isin(big_array, small_array), axis=1)).reshape(-1)
inds_with_fpe = np.argwhere(
np.all(np.isin(big_array, small_array_fpe), axis=1)
).reshape(-1)
print(f"No Floating Point Error: {inds_no_fpe}")
print(f"With Floating Point Error: {inds_with_fpe}")
print(f"Are 5.0 and 5.0+1e-9 close?: {np.isclose(5.0, 5.0 + 1e-9)}")
输出:
No Floating Point Error: [1 3]
With Floating Point Error: []
Are 5.0 and 5.0+1e-9 close?: True
如何通过合并使我的上述解决方案工作(在具有浮点错误的数据集上)np.isclose
?欢迎替代解决方案。
注意: 由于small_array
是 的子集big_array
,因此无法直接使用,np.isclose
因为形状不会广播:
np.isclose(big_array, small_array_fpe)
产量
ValueError: operands could not be broadcast together with shapes (4,3) (2,3)
更新
目前,我唯一可行的解决方案是
inds_with_fpe = [
ndx
for ndx, barr in enumerate(big_array)
for sarr in small_array_fpe
if np.all(np.isclose(sarr, barr))
]