优化python代码 - 过滤numpy数组

时间:2018-01-06 20:02:54

标签: python arrays numpy coordinates

我在2个数组(HLat22和HLong22)中有大量坐标,而且我还有一个LineString。输出是索引 - 有一个完整的True / False数组,它显示HLat22 / HLong22中的坐标与LineString上的坐标有一定的阈值(我的例子是0.005)。在我的例子中,在第4个位置,坐标靠近我的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。

我的问题是:有没有办法优化这段代码并使其更快一点?

1 个答案:

答案 0 :(得分:2)

算法通常会击败低级优化(例如二进制搜索与线性搜索;前者更适合大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)]