我有两个numpy数组,形状为arr1 =(〜140000,3)和arr2 =(〜450000,10)。对于两个数组,每行的前3个元素都是坐标(z,y,x)。我想查找具有与arr1相同的坐标的arr2行(可以将其视为arr2的子组)。
例如:
arr1 = [[1,2,3],[1,2,5],[1,7,8],[5,6,7]]
arr2 = [[1,2,3,7,66,4,3,44,8,9],[1,3,9,6,7,8,3,4,5,2],[1,5,8,68,7,8,13,4,53,2],[5,6,7,6,67,8,63,4,5,20], ...]
我想找到共同的坐标(与前三个元素相同):
list_arr = [[1,2,3,7,66,4,3,44,8,9], [5,6,7,6,67,8,63,4,5,20], ...]
此刻我正在执行此双循环,这非常慢:
list_arr=[]
for i in arr1:
for j in arr2:
if i[0]==j[0] and i[1]==j[1] and i[2]==j[2]:
list_arr.append (j)
我还尝试创建(在第一个循环之后)arr2的子数组,将其过滤为i [0]的值(arr2_filt = [如果el [0] == i [0]则为arr2中的el的el) 。这个速度有点操作,但是仍然很慢。
您能帮我吗?
答案 0 :(得分:3)
这里是views
的矢量化对象-
# https://stackoverflow.com/a/45313353/ @Divakar
def view1D(a, b): # a, b are arrays
a = np.ascontiguousarray(a)
b = np.ascontiguousarray(b)
void_dt = np.dtype((np.void, a.dtype.itemsize * a.shape[1]))
return a.view(void_dt).ravel(), b.view(void_dt).ravel()
a,b = view1D(arr1,arr2[:,:3])
out = arr2[np.in1d(b,a)]
另一个带有dimensionality-reduction
的整数-
d = np.maximum(arr2[:,:3].max(0),arr1.max(0))
s = np.r_[1,d[:-1].cumprod()]
a,b = arr1.dot(s),arr2[:,:3].dot(s)
out = arr2[np.in1d(b,a)]
改进#1
对于先前列出的两种方法,我们可以使用np.searchsorted
代替np.in1d
-
unq_a = np.unique(a)
idx = np.searchsorted(unq_a,b)
idx[idx==len(a)] = 0
out = arr2[unq_a[idx] == b]
改进#2
对于使用np.searchsorted
和np.unique
的最后一项改进,我们可以改用argsort
-
sidx = a.argsort()
idx = np.searchsorted(a,b,sorter=sidx)
idx[idx==len(a)] = 0
out = arr2[a[sidx[idx]]==b]
答案 1 :(得分:1)
您可以在set
的帮助下完成
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2 = np.array([[7,8,9,11,14,34],[23,12,11,10,12,13],[1,2,3,4,5,6]])
# create array from arr2 with only first 3 columns
temp = [i[:3] for i in arr2]
aset = set([tuple(x) for x in arr])
bset = set([tuple(x) for x in temp])
np.array([x for x in aset & bset])
输出
array([[7, 8, 9],
[1, 2, 3]])
修改
使用list comprehension
l = [list(i) for i in arr2 if i[:3] in arr]
print(l)
输出:
[[7, 8, 9, 11, 14, 34], [1, 2, 3, 4, 5, 6]]
答案 2 :(得分:0)
对于整数,Divakar已经给出了一个很好的答案。如果要比较浮点数,则必须考虑以下:
1.+1e-15==1.
False
1.+1e-16==1.
True
如果这种行为可能导致您的代码出现问题,我建议执行最近邻居搜索,并可能检查距离是否在指定的阈值内。
import numpy as np
from scipy import spatial
def get_indices_of_nearest_neighbours(arr1,arr2):
tree=spatial.cKDTree(arr2[:,0:3])
#You can check here if the distance is small enough and otherwise raise an error
dist,ind=tree.query(arr1, k=1)
return ind