numpy广播的困难

numpy广播的困难,numpy,distance,linear-algebra,Numpy,Distance,Linear Algebra,我有两个二维点云(oldPts和newPts),我希望将它们合并。它们是mx2和nx2 numpyinteger阵列,m和n的阶数为2000。newPts包含许多旧pts的重复项或近似重复项,我需要在合并之前删除它们 到目前为止,我已经使用histogram2d函数来生成oldPts(H)的2d表示。然后,我将每个newPt与H的NxN区域进行比较,如果它为空,我接受该点。最后一部分是我目前正在做的一个python循环,我想删除它。有谁能告诉我如何通过广播做到这一点,或者提出一种完全不同的解决问

我有两个二维点云(oldPts和newPts),我希望将它们合并。它们是mx2和nx2 numpyinteger阵列,m和n的阶数为2000。newPts包含许多旧pts的重复项或近似重复项,我需要在合并之前删除它们

到目前为止,我已经使用histogram2d函数来生成oldPts(H)的2d表示。然后,我将每个newPt与H的NxN区域进行比较,如果它为空,我接受该点。最后一部分是我目前正在做的一个python循环,我想删除它。有谁能告诉我如何通过广播做到这一点,或者提出一种完全不同的解决问题的方法吗。工作代码如下

npzfile = np.load(path+datasetNo+'\\temp.npz')
arrs = npzfile.files
oldPts = npzfile[arrs[0]]
newPts = npzfile[arrs[1]]

# remove all the negative values 
oldPts = oldPts[oldPts.min(axis=1)>=0,:]
newPts = newPts[newPts.min(axis=1)>=0,:]

# round to integers
oldPts = np.around(oldPts).astype(int)
newPts = newPts.astype(int)

# put the oldPts into 2d array
H, xedg,yedg= np.histogram2d(oldPts[:,0],oldPts[:,1],
                         bins = [xMax,yMax], 
                         range = [[0, xMax], [0, yMax]])
finalNewList = []
N = 5
for pt in newPts:

    if not H[max(0,pt[0]-N):min(xMax,pt[0]+N),
         max(0,pt[1]- N):min(yMax,pt[1]+N)].any():
        finalNewList.append(pt)

finalNew = np.array(finalNewList)  

正确的方法是使用线性代数计算每对2长向量之间的距离,然后只接受与每个旧点“足够不同”的新点:使用:

上面我使用欧几里德距离5作为“太近”的阈值:
newPts
中任何距离
oldPts
中所有点超过5的点都被接受为
finalPts
。您必须查看
dist
中的值范围才能找到一个好的阈值,但直方图可以指导您选择最佳阈值

(可视化
dist
的一个好方法是使用
matplotlib.pyplot.imshow(dist)

这是一个更完善的版本,你正在做的直方图。事实上,您应该能够通过将
metric='minkowski',p=1
关键字参数传递到
cdist
,从而获得与直方图完全相同的答案,假设您的直方图箱宽度在两个维度上相同,并再次使用5作为阈值


(注:如果您对scipy.spatial.distance中的另一个有用函数感兴趣,请检查。)

正确的方法是使用线性代数计算每对2长向量之间的距离,然后只接受与每个旧点“足够不同”的新点:使用:

上面我使用欧几里德距离5作为“太近”的阈值:
newPts
中任何距离
oldPts
中所有点超过5的点都被接受为
finalPts
。您必须查看
dist
中的值范围才能找到一个好的阈值,但直方图可以指导您选择最佳阈值

(可视化
dist
的一个好方法是使用
matplotlib.pyplot.imshow(dist)

这是一个更完善的版本,你正在做的直方图。事实上,您应该能够通过将
metric='minkowski',p=1
关键字参数传递到
cdist
,从而获得与直方图完全相同的答案,假设您的直方图箱宽度在两个维度上相同,并再次使用5作为阈值


(另外,如果您对
scipy.space.distance
中的另一个有用函数感兴趣,请检查。)

你能发布
npz
输入文件吗,或者以某种方式伪造它,这样我们就有了一个完整的例子可以测试了?这里是一个指向npz文件的链接,你能发布
npz
输入文件吗,或者以某种方式伪造它吗,这样我们就有了一个完整的例子可以测试了?这里是一个指向npz文件的链接,谢谢你花时间回答,然而,这可能是正确的方式,也是显而易见的方式,但它比我展示的方式慢了3倍,如果我能解决广播问题,我希望加快速度。jupyter笔记本中的计时,其中50.1 ms±5.35 ms/循环(平均±标准偏差7次,每个循环10次)和152 ms±973µs/循环(平均±标准偏差7次,每个循环10次)使用kdtrees可能会产生更好的时间,但我不是专家。是的,kd树很好:请参见相反的问题,问题是如何在两个数组中找到相同的点,但您可以很容易地调整它以找到不同的点。是的,
cdist
做的工作比您需要的多得多(因为如果您在
oldPts
中发现一个点太接近
newPts
中的一个点,您可以立即消除它,而不是列举所有其他旧点)。感谢您花时间回答,然而,这可能是正确的方式,也是显而易见的方式,但它比我展示的方式慢了3倍,如果我能解决广播问题,我希望加快速度。jupyter笔记本中的计时,其中50.1 ms±5.35 ms/循环(平均±标准偏差7次,每个循环10次)和152 ms±973µs/循环(平均±标准偏差7次,每个循环10次)使用kdtrees可能会产生更好的时间,但我不是专家。是的,kd树很好:请参见相反的问题,问题是如何在两个数组中找到相同的点,但您可以很容易地调整它以找到不同的点。是的,
cdist
做的工作比您需要的多得多(因为如果您在
oldPts
中发现一个点太接近
newPts
中的一个点,您可以立即消除它,而不是枚举所有其他旧点)。
import numpy as np
oldPts = np.random.randn(1000,2)
newPts = np.random.randn(2000,2)

from scipy.spatial.distance import cdist
dist = cdist(oldPts, newPts)
print(dist.shape) # (1000, 2000)

okIndex = np.max(dist, axis=0) > 5
print(np.sum(okIndex)) # prints 1503 for me

finalNew = newPts[okIndex,:]
print(finalNew.shape) # (1503, 2)