如何在numpy数组中找到最近的值?例子:
np.find_nearest(array, value)
如何在numpy数组中找到最近的值?例子:
np.find_nearest(array, value)
当前回答
稍微修改一下,上面的答案适用于任意维度的数组(1d, 2d, 3d,…):
def find_nearest(a, a0):
"Element in nd array `a` closest to the scalar value `a0`"
idx = np.abs(a - a0).argmin()
return a.flat[idx]
或者,写成一行:
a.flat[np.abs(a - a0).argmin()]
其他回答
所有的答案都有助于收集信息来编写高效的代码。但是,我已经编写了一个小的Python脚本来针对各种情况进行优化。如果提供的数组已排序,则将是最佳情况。如果搜索一个指定值的最近点的索引,那么对半模块是最省时的。当一个索引对应一个数组时,numpy searchsorted是最有效的。
import numpy as np
import bisect
xarr = np.random.rand(int(1e7))
srt_ind = xarr.argsort()
xar = xarr.copy()[srt_ind]
xlist = xar.tolist()
bisect.bisect_left(xlist, 0.3)
In[63]: %时间平分。bisect_left (xlist, 0.3) CPU次数:user 0ns, sys: 0ns, total: 0ns 壁时间:22.2µs
np.searchsorted(xar, 0.3, side="left")
In [64]: %time np。Searchsorted (xar, 0.3, side="left") CPU次数:user 0ns, sys: 0ns, total: 0ns 壁时间:98.9µs
randpts = np.random.rand(1000)
np.searchsorted(xar, randpts, side="left")
%的时间np。Searchsorted (xar, randpts, side="left") CPU次数:用户4ms, sys: 0ns, total: 4ms 壁时间:1.2 ms
如果我们遵循乘法规则,那么numpy应该花费~100 ms,这意味着快了~83倍。
我认为最python的方式是:
num = 65 # Input number
array = np.random.random((10))*100 # Given array
nearest_idx = np.where(abs(array-num)==abs(array-num).min())[0] # If you want the index of the element of array (array) nearest to the the given number (num)
nearest_val = array[abs(array-num)==abs(array-num).min()] # If you directly want the element of array (array) nearest to the given number (num)
这是基本代码。你可以把它作为一个函数来使用
如果你的数组已经排序并且非常大,这是一个更快的解决方案:
def find_nearest(array,value):
idx = np.searchsorted(array, value, side="left")
if idx > 0 and (idx == len(array) or math.fabs(value - array[idx-1]) < math.fabs(value - array[idx])):
return array[idx-1]
else:
return array[idx]
这可以扩展到非常大的阵列。如果不能假定数组已经排序,可以很容易地修改上面的内容以在方法中排序。对于小型数组来说,这是多余的,但一旦它们变大,这就快得多了。
也许对ndarray有帮助:
def find_nearest(X, value):
return X[np.unravel_index(np.argmin(np.abs(X - value)), X.shape)]
下面是一个使用2D数组的版本,如果用户拥有scipy的cdist函数,则使用它,如果用户没有,则使用更简单的距离计算。
默认情况下,输出是最接近输入值的索引,但您可以使用output关键字将其更改为'index', 'value'或'both'之一,其中'value'输出数组[index], 'both'输出索引,数组[index]。
对于非常大的数组,您可能需要使用kind='euclidean',因为默认的scipy cdist函数可能会耗尽内存。
这可能不是绝对最快的解决方案,但已经很接近了。
def find_nearest_2d(array, value, kind='cdist', output='index'):
# 'array' must be a 2D array
# 'value' must be a 1D array with 2 elements
# 'kind' defines what method to use to calculate the distances. Can choose one
# of 'cdist' (default) or 'euclidean'. Choose 'euclidean' for very large
# arrays. Otherwise, cdist is much faster.
# 'output' defines what the output should be. Can be 'index' (default) to return
# the index of the array that is closest to the value, 'value' to return the
# value that is closest, or 'both' to return index,value
import numpy as np
if kind == 'cdist':
try: from scipy.spatial.distance import cdist
except ImportError:
print("Warning (find_nearest_2d): Could not import cdist. Reverting to simpler distance calculation")
kind = 'euclidean'
index = np.where(array == value)[0] # Make sure the value isn't in the array
if index.size == 0:
if kind == 'cdist': index = np.argmin(cdist([value],array)[0])
elif kind == 'euclidean': index = np.argmin(np.sum((np.array(array)-np.array(value))**2.,axis=1))
else: raise ValueError("Keyword 'kind' must be one of 'cdist' or 'euclidean'")
if output == 'index': return index
elif output == 'value': return array[index]
elif output == 'both': return index,array[index]
else: raise ValueError("Keyword 'output' must be one of 'index', 'value', or 'both'")