【问题标题】:Increasing performance with octant search algorithm使用八分圆搜索算法提高性能
【发布时间】:2017-01-19 09:34:35
【问题描述】:

我正在进行八分圆搜索,以在每个八分圆中找到最接近我的圆形点 (o) 的点 (+) 的 n 数(例如 8)。这意味着我的点 (+) 减少到只有 64(每个八分圆 8)。

我做的第一件事是以我的点 (o) 作为参考,将我的区域划分为八分圆。

data = 包含所有点 (+) 的 (x, y, z) 数组 gdata = 包含点 (o) 的 (x, y) 的数组

import tkinter as tk
from tkinter import filedialog
import pandas as pd
import numpy as np
from scipy.spatial.distance import cdist
from collections import defaultdict

root = tk.Tk()
root.withdraw()
file_path = filedialog.askopenfilename()
data = pd.read_excel(file_path)
data = np.array(data, dtype=np.float)
nrow, cols = data.shape

file_path1 = filedialog.askopenfilename()
gdata = pd.read_excel(file_path1)
gdata = np.array(gdata, dtype=np.float)

pwangle = np.zeros(nrow)

for j in range(nrow):
    delta_x = gdata[:,0]-data[:,0][j]
    delta_y = gdata[:,1]-data[:,1][j]
    if delta_x != 0:
        pwangle[j] = np.rad2deg(np.arctan(delta_y/delta_x))
    else:
        if delta_y > 0:
            pwangle[j] = 90
        elif delta_y < 0:
            pwangle[j] = 270
    if (delta_x < 0)&(delta_y > 0):
        pwangle[j] = 180 + pwangle[j]
    elif (delta_x < 0)&(delta_y < 0):
        pwangle[j] = 270 - pwangle[j]
    elif (delta_x > 0)&(delta_y < 0):
        pwangle[j] = 360 + pwangle[j]

vecangle = pwangle.ravel()
sortdata = defaultdict(list)
count = -1
get_anglesector = 45

N = 8
d = cdist(data[:,:2], gdata)
P = np.hstack((data, d)) 

for j in range(0, 360, get_anglesector):
    count += 1
    get_data = []
    for k, dummy_val in enumerate(vecangle):
        if j <= vecangle[k] < j + get_anglesector:
            get_data.append(P[k,::])
            sortdata[count] = np.array(get_data)

在将数据分组到各个八分圆后,我对每个八分圆中的数据进行排序,以获得最接近点 (o) 的 8 个数据。

for i, j in enumerate(sortdata):   
    octantsort = defaultdict(list)
    for i in range(8):
        octantsort[i] = np.array(sortdata[i][sortdata[i][:,3].argsort()[:N]])

有没有一种高效的 Pythonic 方式来提高性能?

这很好用,但是当我有多个“o”点(例如 10000 个“o”点)并且我已经为每个点运行了上述代码时,这将非常耗时。

【问题讨论】:

    标签: python performance python-3.x numpy search


    【解决方案1】:

    如果您使用arctan2 而不是arctan,工作会变得容易得多。然后向量化速度,我们可能会得到这样的结果:

    import numpy as np
    from scipy.spatial.distance import cdist
    
    delta = gdata - data[:,:2]
    angles = np.arctan2(delta[:,1], delta[:,0])
    bins = np.linspace(-np.pi, np.pi, 9)
    bins[-1] = np.inf  # handle edge case
    octantsort = []
    for i in range(8):
        data_i = data[(bins[i] <= angles) & (angles < bins[i+1])]
        dist_order = np.argsort(cdist(data_i, gdata))
        octantsort.append(data_i[dist_order[:N]])
    

    【讨论】:

    • 如果我在获得 'octantsort` 中的元素后,我想获得最接近圆形点 (o) 且未出现在 'octantsort` 中的前 10 个元素。对于第二种情况,bins =np.linspace(-np.pi + np.pi/8, np.pi + np.pi/8, 9)。我怎样才能有效地做到这一点?
    【解决方案2】:

    谢谢@user7138814,除了做些小改动,你的代码更快了

    N=8  
    delta = gdata - data[:,:2]
    angles = np.arctan2(delta[:,1], delta[:,0])
    bins = np.linspace(-np.pi, np.pi, 9)
    bins[-1] = np.inf  # handle edge case
    octantsort = []
    for i in range(8):
        data_i = data[(bins[i] <= angles) & (angles < bins[i+1])]
        dist_order = np.argsort(cdist(data_i[:,:2], gdata), axis=0)
        [octantsort.append(data_i[dist_order[:N][j]]) for j in range(8)]
    final = np.vstack(octantsort)
    

    前面代码的执行时间(问题中的代码):

     ---- 0.021449804306030273 seconds ------
    

    本帖代码执行时间:

    ---- 0.0015172958374023438 seconds ------
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      • 2018-12-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多