【问题标题】:Optimizing python code - filtering numpy arrays优化python代码——过滤numpy数组
【发布时间】:2018-01-06 20:02:53
【问题描述】:

我在 2 个数组(HLat22 和 HLong22)中有大量坐标,而且我还有一个 LineString。输出在索引中 - 有一个充满 True/False 的数组,它向我显示 HLat22/HLong22 中的坐标,这些坐标与我的 LineString 上的坐标处于某个阈值(我的示例是 0.005)。在我的示例中,第四个位置的坐标靠近我的 LineString。

对于过滤功能,我使用了这篇文章中的功能: Selecting close matches from one array based on another reference array

def searchsorted_filter(a, b, thresh):
    choices = np.sort(b) # if b is already sorted, skip it
    lidx = np.searchsorted(choices, a, 'left').clip(max=choices.size-1)
    ridx = (np.searchsorted(choices, a, 'right')-1).clip(min=0)
    cl = np.take(choices,lidx) # Or choices[lidx]
    cr = np.take(choices,ridx) # Or choices[ridx]
    return a[np.minimum(np.abs(a - cl), np.abs(a - cr)) < thresh]

from shapely.geometry import LineString, Point, LinearRing
import time
import numpy as np

start_time = time.time()
HLat22 = np.asarray([100,200,300,32.47156,500,600,700,800,900,1000])
HLong22 = np.asarray([-100,-200,-300,-86.79192,-500,-600,-700,-800,-900,-1000])
polygon2 = LineString ([Point(-86.79191,32.47155), Point(-86.78679699999999,32.47005)])

#Getting lat and long coordinates
numpy_x = np.array(polygon2.coords.xy[0])
numpy_y = np.array(polygon2.coords.xy[1])

#Filtering so I only remain with coordinates 
The_X = searchsorted_filter(HLong22,numpy_x,thresh=0.005)
The_Y = searchsorted_filter(HLat22,numpy_y,thresh=0.005)

print("Secsfilter: %s",time.time()-start_time)
start_time = time.time()
indices = np.in1d(HLong22, The_X) & np.in1d(HLat22, The_Y)
print("Secsin1d: %s",time.time()-start_time)

输出:

Secsfilter: %s 0.002005338668823242
Secsin1d: %s 0.0 
array([False, False, False,  True, False, False, False, False, False, False], dtype=bool)

这很好用。然而,随着更大的输出,它开始变得更慢。如果我的 HLat2/Hlong2 的大小为 1413917(相同的 LineString ),这就是它的行为方式:

Secsfilter: %s 0.20999622344970703
Secsin1d: %s 0.49498486518859863

The_X 和 The_Y 的长度为 15249。

我的问题是:有什么办法可以优化这段代码,让它更快一点?

【问题讨论】:

  • 你能解释一下你的 searchsorted 函数吗?
  • 这个任务从哪里来?我想知道这是否真的是您所需要的,或者已经尝试加快速度(例如,让所有都在距离内,而不是让所有分解的单暗距离在范围内)?
  • 你是对的。我的任务是获取线串距离内的所有坐标。在我过滤坐标后,我的线串只有 0.005 纬度/经度的坐标,我计算线串上离我剩余的每个坐标最近的点,然后在最近的点和我的坐标上使用半正弦。不过这些工作真的很快,我对它们没有任何问题。
  • 试图更好地优化来自 Divakar 的帖子将很难做到 :)。
  • 用更好的解决方案更新了链接帖子的解决方案。

标签: python arrays numpy coordinates


【解决方案1】:

算法通常击败低级优化(例如,二分搜索与线性搜索;前者更适合大 n;后者更适合小 n)。

在这方面没有太多经验并且完全忽略了您提供的数字,这里有一些您应该尝试的演示! 您必须为您的任务量身定制自己的基准测试(并调整可用参数)!

想法是:

  • 使用metric-trees,它们是用于在某些度量空间中进行类似最近邻搜索的专用数据结构

代码:

from sklearn.neighbors import BallTree
import numpy as np

Coords = np.array([[51.165691, 10.451526],  # GER
                   [40.463667, -3.74922],   # ESP
                   [61.52401, 105.318756]]) # RUS
print(Coords)

polygon2 = np.array([[52.520008, 13.404954],   # BERLIN
                     [55.751244, 37.618423]])  # MOSCOW
print(polygon2)

# BUILD TREE for LOOKUP
tree = BallTree(Coords, metric='haversine')

# QUERY NEAREST NEIGHBORS
print('\nnearest neighbor search')
dist, ind = tree.query(polygon2, k=1)
print('dist: ', dist)
print('indices: ', ind)     

# QUERY FOR DISTANCE <= X
print('\nradius search')
ind = tree.query_radius(polygon2[0][np.newaxis], 0.15)
print('indices: ', ind)

输出

[[  51.165691   10.451526]
 [  40.463667   -3.74922 ]
 [  61.52401   105.318756]]
[[ 52.520008  13.404954]
 [ 55.751244  37.618423]]

nearest neighbor search
dist:  [[ 0.11852066]
 [ 0.76816021]]
indices:  [[0]
 [2]]

radius search
indices:  [array([0], dtype=int64)]

【讨论】:

  • 是的,这看起来很棒!我已经测试了一下,似乎真的很快。一个快速说明:对于那些尝试这种方法的人,您需要将 lat/long 转换为弧度,以使输出以弧度为单位正确。
猜你喜欢
  • 2014-06-24
  • 2022-10-06
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-07-05
  • 1970-01-01
  • 2013-08-10
  • 1970-01-01
相关资源
最近更新 更多