python

时间:2017-03-13 03:53:32

标签: python loops numpy

我有两个大点名单。一个包含表示矩形边缘的点(edge_points)。 Edge_points具有xy坐标。另一个列表包含矩形内的点(all_point)。 All_point具有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

1 个答案:

答案 0 :(得分:0)

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级别没有更多循环。 Vectorization将这些循环移动到编译后的代码,执行速度提高了几倍。

具体来说,我们创建了两个大小为all_point且大小为N1x2的{​​{1}}的{​​{1}}阵列。然后将这些内容重新调整为大小edge_pointsN2x2(通过索引中的N1x1x2)。

当取得差异时,会触发前两个轴的广播,这样得到的数组的形状为1xN2x2,并且包含NoneN1xN2x2坐标之间的所有成对差异。随后的平方一次性适用于所有all_point个元素。 edge_points参数指定的总和沿着最后一个轴,即N1xN2x2axis,以产生成对距离的x数组。

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

此蒙版在形状上与all匹配,可用于提取符合标准的所有坐标对。

总结允许从Python级别消除嵌套循环的广播,并用一些矢量化操作替换它。只要内存不是问题,这就会带来巨大的加速。

如果内存有问题:以下是使用N1

的节省内存的变体
all_point

如果仍然太大,我们必须将tensordotall_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