Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python中不同大小列表中坐标的有效欧氏距离_Python_Loops_Numpy - Fatal编程技术网

python中不同大小列表中坐标的有效欧氏距离

python中不同大小列表中坐标的有效欧氏距离,python,loops,numpy,Python,Loops,Numpy,我有两大要点清单。其中包含表示矩形边的点(边点)。边_点具有xy坐标。另一个列表包含矩形内的点(所有点)。所有_点都有xyz坐标。在第二个列表中,我要删除与边周围的点之间xy“m”距离内的任何点(列表1) 我有一个运行的代码,但它是非常缓慢的嵌套循环。。。我见过一些线程建议使用cdist,但这不适用于我想将矩形中的每个点与单个边缘点进行比较的场景。Hypot比使用sqrt更快,但仍然无法达到我想要的效果 如何提高此代码的效率 all_point=colpoint+rowpoint all_poi

我有两大要点清单。其中包含表示矩形边的点(边点)。边_点具有xy坐标。另一个列表包含矩形内的点(所有点)。所有_点都有xyz坐标。在第二个列表中,我要删除与边周围的点之间xy“m”距离内的任何点(列表1)

我有一个运行的代码,但它是非常缓慢的嵌套循环。。。我见过一些线程建议使用cdist,但这不适用于我想将矩形中的每个点与单个边缘点进行比较的场景。Hypot比使用sqrt更快,但仍然无法达到我想要的效果

如何提高此代码的效率

all_point=colpoint+rowpoint
all_points=[]
for n in range(0,len(all_point)):
    #Calculate xy distance between inflection point and edge points
    test_point=all_point[n]
    dist=[]
    for k in range(0,len(edge_points)):
        test_edge=edge_points[k]
        dist_edge=math.hypot((test_point[1]-test_edge[1])+(test_point[0]-test_edge[0]))
        dist.append(dist_edge)
    if all(i >= m for i in dist) is True:
        all_points.append(test_point)
    else:
        continue
Vectorise,Vectorise也适用于此:

import numpy as np

all_point, edge_points = np.asanyarray(all_point), np.asanyarray(edge_points)
squared_dists = ((all_point[:, None, :2] - edge_points[None, :, :])**2).sum(axis=-1)
mask = np.all(squared_dists > m**2, axis=-1)
all_points = all_point[mask, :]
请注意,在Python级别上没有更多的循环。矢量化将这些循环移动到执行速度快几倍的编译代码中

具体而言,我们创建了两个数组
大小为
N1x2
的所有\u点
,以及大小为
N2x2
边缘\u点
。然后将其重塑为
N1x1x2
1xN2x2
(通过索引中的
None
s)

获取差异时,这会触发前两个轴的广播,从而生成的阵列具有形状
N1xN2x2
,并包含
所有_点
边缘_点
坐标之间的所有成对差异。随后的平方运算一次性应用于所有
N1xN2x2
元素。由
参数指定的总和沿着最后一个轴,即在
x
y
上取,以产生一个成对距离平方的
N1xN2
数组

下面几行演示了
if
语句的向量化等价物。为了能够一次完成,我们创造了真相面具。与
m**2
的比较是按元素进行的,因此我们为
squared_dists
的每个
N1xN2
元素获得一个真值
np.all
类似于Python
all
,但可以同时执行多个组。这由
参数控制。这里它指定应按行应用
all
,以产生
N1
真值

此遮罩在形状上与
所有点
匹配,并可用于提取满足标准的所有坐标对

总结一下,可以从Python级别消除嵌套循环,并用一些向量化操作来替换它。只要内存不是问题,这将带来巨大的加速

如果内存有问题:这里有一个使用
tensordot

all_point, edge_points = np.asanyarray(all_point), np.asanyarray(edge_points)
mixed = np.tensordot(all_point[:, :2], -2 * edge_points, (1, 1))
mixed += (all_point[:, :2]**2).sum(axis=-1)[:, None]
mixed += (edge_points**2).sum(axis=-1)[None, :]
mask = np.all(mixed > m**2, axis=-1)
all_points = all_point[mask, :]
如果仍然太大,我们必须将
所有点
边缘点
分割成可管理的位

all_point, edge_points = np.asanyarray(all_point), np.asanyarray(edge_points)
mask = np.ones((len(all_point),), dtype=bool)
mm = m*m - (all_point[:,:2]**2).sum(axis=-1)[:, None]
chunksize = <choose according to your memory and data size>
for i in range(0, len(edge_points), chunksize):
    mixed = np.tensordot(all_point[mask, :2], -2 * edge_points[i:i+chunksize, :], (1, 1))
    mixed += (edge_points[None, i:i+chunksize, :]**2).sum(axis=-1)
    mask[mask] &= np.all(mixed > mm[mask], axis=-1)
all_points = all_point[mask, :]
all_point,edge_points=np.asanyarray(all_point),np.asanyarray(edge_points)
掩码=np.ones((len(所有点)),数据类型=bool)
mm=m*m-(所有点[:,:2]**2)。和(轴=-1)[:无]
chunksize=
对于范围内的i(0,len(边_点),chunksize):
mixed=np.tensordot(所有点[mask,:2],-2*边点[i:i+chunksize,:],(1,1))
混合+=(边缘点[None,i:i+chunksize,:]**2)。求和(轴=-1)
遮罩[遮罩]&=np.all(混合>毫米[遮罩],轴=-1)
所有_点=所有_点[遮罩,:]

如果我误解了,很抱歉,但是为什么您不能使用cdist?您可以将矩形中每个点的列表作为第一个参数,将单个点作为sklearn cdist的第二个参数。您可能应该使用numpy来实现这一点,并将循环矢量化。单是这一点就应该给你带来巨大的加速。是的,你可能不会比sklearn.metrics.pairwise.pairwise\u distance跑得更快。我忘了提到列表1是2D的,列表2是3D的。。。。我不知道如何在没有更多循环的情况下协调cdist的这些点。有什么想法吗?所以用我当前的列表运行这个,一个有xy点,一个有xyz点,会抛出一个错误,因为维度不一样。。。。为我的边_点添加了一些占位符z值(需要所有_点的z值),它引发了内存错误。不知道该怎么办。@JCH您的列表有多大?代替填充占位符,您可以切掉z。我将把它添加到代码中,以及其他一些节省内存的策略。@JCH我已经添加到节省内存的变体中。第二个有一个参数
chunksize
,您可以调整该参数以控制内存消耗。边缘点约为1700点,所有点约为18000点。这对于我需要运行的线束(矩形)来说非常典型。我将尝试一下你的新建议,第二个代码运行得非常好!现在的总运行时间大约是20秒,而之前的时间超过一分钟。我将花一些时间试图理解向量化循环。。。。我还有一些其他的嵌套循环,可以使用这种逻辑来加速。谢谢