所以我正在嘗試撰寫一個 python 函式,它可以獲取任何給定的點,比如(1,2),我們可以稱之為興趣點,然后獲取點串列,比如[(6,2), (4,5), (3,4),...]函式應該回傳離我們的興趣點最近和最遠的點(從串列中) 。
該函式應接受兩個引數:
1. Point of interest i.e. pos=(1,2)
2. List of points i.e. ptlist=[(1,3),(6,2), (4,5), (3,4)]
該函式還應該以 ((1,3),(4,5)) 的形式回傳答案,即(最近的,最遠的)
這是我的代碼,到目前為止它有效,但它回傳 numpy 陣列,而我希望我的答案是元組。我嘗試了不同的方法,無論我嘗試什么,我似乎都無法做到。也許我們可以使用除 numpy 之外的其他東西,以便我們以 ((1,3),(4,5)) 的形式獲得答案。
這是我到目前為止撰寫的代碼:
pos=(1,2)
ptlist=[(2, 6), (8,6), (5,8), (2,4)]
def get_nearest_farthest(pt, ptlist):
pt=np.array(pt)
ptlist=np.array(ptlist)
dist=np.linalg.norm(ptlist-pt, axis=1)
min_index = np.argmin(dist)
#tuple(map(tuple,ptlist[min_index])) #Error
max_index = np.argmax(dist)
#tuple(map(tuple,ptlist[max_index])) #Error
return ptlist[min_index],ptlist[max_index]
get_nearest_farthest(pt, ptlist)
uj5u.com熱心網友回復:
你不需要numpy這個。您只需要min()/max()帶一個key引數:
distance_metric = lambda x: (x[0] - pos[0])**2 (x[1] - pos[1])**2
closest = min(ptlist, key=distance_metric)
farthest = max(ptlist, key=distance_metric)
print(closest, farthest)
這輸出:
(2, 4) (8, 6)
uj5u.com熱心網友回復:
這將在不使用 numpy 的情況下到達那里,并且非常有效,只需對串列中的每個點進行一次距離計算。
def get_nearest_farthest(pos, pt_list):
nearest_pt, farthest_pt = None, None
nearest_d, farthest_d = None, None
for pt in pt_list:
d = (pos[0]-pt[0])**2 (pos[1]-pt[1])**2
if nearest_d is None or d < nearest_d:
nearest_d = d
nearest_pt = pt
if farthest_d is None or d > farthest_d:
farthest_d = d
farthest_pt = pt
return nearest_pt, farthest_pt
pos = (1,2)
pt_list = [(2, 6), (8,6), (5,8), (2,4)]
get_nearest_farthest(pos, pt_list)
uj5u.com熱心網友回復:
有許多方法可以解決這個問題。你的就是其中之一,要以元組的形式獲得結果,只需將結果陣列轉換回list,并結合tuple()和np.ndarray.tolist()。
就最快的執行而言,這一切都歸結為輸入的大小。
在這里,我提供了一些實作(一些類似于其他答案)以及一些時間:
import numpy as np
def p_dist_np(x, y, p=2):
if p % 2:
return np.sum(np.abs(x - y) ** p, axis=-1)
else:
return np.sum((x - y) ** p, axis=-1)
def minmax_dist_np(x0, xs, d_func=p_dist_np):
x0 = np.array(x0)
xs = np.array(xs)
dists = d_func(x0, xs)
min_i = np.argmin(dists)
max_i = np.argmax(dists)
return tuple(xs[min_i].tolist()), tuple(xs[max_i].tolist())
import numpy as np
import numba as nb
@nb.njit
def p_dist_nb(x, y, p=2):
if p % 2:
return np.sum(np.abs(x - y) ** p)
else:
return np.sum((x - y) ** p)
@nb.njit
def _minmax_dist_nb(x0, xs, d_func=p_dist_nb):
min_i = max_i = 0
min_d = max_d = d_func(x0, xs[min_i])
for i, x in enumerate(xs[1:], 1):
d = d_func(x0, x)
if d < min_d:
min_d = d
min_i = i
elif d > max_d:
max_d = d
max_i = i
return min_i, max_i
def minmax_dist_nb(x0, xs, d_func=p_dist_nb):
x0 = np.array(x0)
xs = np.array(xs)
min_i, max_i = _minmax_dist_nb(x0, xs, d_func=d_func)
return tuple(xs[min_i].tolist()), tuple(xs[max_i].tolist())
def p_dist(x, y, p=2):
if p % 2:
return sum(abs(x_i - y_i) ** p for x_i, y_i in zip(x, y))
else:
return sum((x_i - y_i) ** p for x_i, y_i in zip(x, y))
def minmax_dist_loop(x0, xs, d_func=p_dist):
i_xs = iter(xs)
min_i = max_i = 0
min_d = max_d = d_func(x0, next(i_xs))
for i, x in enumerate(i_xs, 1):
d = d_func(x0, x)
if d < min_d:
min_d = d
min_i = i
elif d > max_d:
max_d = d
max_i = i
return xs[min_i], xs[max_i]
def minmax_dist_key(x0, xs, d_func=p_dist):
return (
min(xs, key=lambda x: d_func(x, x0)),
max(xs, key=lambda x: d_func(x, x0)))
以及獲取時間的代碼:
x0 = (1, 2)
xs = [(2, 6), (8, 6), (5, 8), (2, 4)]
funcs = minmax_dist_np, minmax_dist_loop, minmax_dist_key, minmax_dist_nb
for n in (1, 10, 100, 1000):
nxs = xs * n
print(f"N = {n * len(xs)}")
base = funcs[0](x0, nxs)
for func in funcs:
res = func(x0, nxs)
print(f"{func.__name__:>24} {base == res}", end=' ')
%timeit -n 50 func(x0, nxs)
# N = 4
# minmax_dist_np True 50 loops, best of 5: 16.2 μs per loop
# minmax_dist_loop True 50 loops, best of 5: 6.11 μs per loop
# minmax_dist_key True 50 loops, best of 5: 11.6 μs per loop
# minmax_dist_nb True 50 loops, best of 5: 18.1 μs per loop
# N = 40
# minmax_dist_np True 50 loops, best of 5: 39.6 μs per loop
# minmax_dist_loop True 50 loops, best of 5: 54.3 μs per loop
# minmax_dist_key True 50 loops, best of 5: 107 μs per loop
# minmax_dist_nb True 50 loops, best of 5: 43.2 μs per loop
# N = 400
# minmax_dist_np True 50 loops, best of 5: 232 μs per loop
# minmax_dist_loop True 50 loops, best of 5: 550 μs per loop
# minmax_dist_key True 50 loops, best of 5: 1.07 ms per loop
# minmax_dist_nb True 50 loops, best of 5: 281 μs per loop
# N = 4000
# minmax_dist_np True 50 loops, best of 5: 2.28 ms per loop
# minmax_dist_loop True 50 loops, best of 5: 5.7 ms per loop
# minmax_dist_key True 50 loops, best of 5: 11.3 ms per loop
# minmax_dist_nb True 50 loops, best of 5: 2.78 ms per loop
表明對于足夠小的輸入,minmax_dist_loop()是最快的,但是一旦輸入變大,minmax_dist_np()并且minmax_dist_nb()以公平的幅度接管。相反,minmax_dist_key()逐漸變得最慢,主要是因為它需要計算兩倍于的昂貴距離minmax_dist_loop()函式。雖然對于 的回圈也計算了兩次minmax_dist_np(),但距離的計算只進行了一次(以創建一個可能很大的臨時物件為代價)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/479488.html
上一篇:如何壓縮資料幀,以使行間差異至少在幅度上達到某個閾值
下一篇:numpy中是否有二維“位置”?
