উত্তর:
import numpy as np
def find_nearest(array, value):
array = np.asarray(array)
idx = (np.abs(array - value)).argmin()
return array[idx]
array = np.random.random(10)
print(array)
# [ 0.21069679 0.61290182 0.63425412 0.84635244 0.91599191 0.00213826
# 0.17104965 0.56874386 0.57319379 0.28719469]
value = 0.5
print(find_nearest(array, value))
# 0.568743859261
FutureWarning: 'argmin' is deprecated. Use 'idxmin' instead. The behavior of 'argmin' will be corrected to return the positional minimum in the future. Use 'series.values.argmin' to get the position of the minimum now.
idxmin
পরিবর্তে ব্যবহার করে argmin
উপরের সমাধানটি আমার সাথে কাজ করে। (v3.6.4)
যদি আপনার অ্যারে বাছাই করা হয় এবং খুব বড় হয় তবে এটি আরও দ্রুত সমাধান:
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]
এটি খুব বড় অ্যারেগুলিতে স্কেল করে। অ্যারেটি ইতিমধ্যে সাজানো হয়েছে যদি আপনি ধরে নিতে না পারেন তবে আপনি পদ্ধতিটিতে বাছাই করতে সহজেই উপরেরটি সংশোধন করতে পারেন। এটি ছোট অ্যারেগুলির জন্য ওভারকিল, তবে তারা একবার বড় হয়ে গেলে এটি আরও দ্রুত।
np.searchsorted
আমার পরীক্ষার সেটটির জন্য প্রায় 2 µ সে সময় নেয়, পুরো ফাংশনটি প্রায় 10। Μ np.abs
এটি আরও খারাপ হচ্ছে ব্যবহার করে। অজগর সেখানে কী করছে সে সম্পর্কে কোনও ধারণা নেই।
math
রুটিনের চেয়ে ধীর হবে , এই উত্তরটি দেখুন ।
if/else
চাহিদার সঙ্গে প্রতিস্থাপন করাidx = idx - (np.abs(value - array[idx-1]) < np.abs(value - array[idx])); return array[idx]
value
চেয়ে বড় হলে কাজ করে না array
। আমি if
বিবৃতিটি if idx == len(array) or math.fabs(value - array[idx - 1]) < math.fabs(value - array[idx])
এটির জন্য কার্যকর করে তুললাম!
if idx > 0 and (idx == len(array) or math.fabs(value - array[idx-1]) < math.fabs(value - array[idx])):
সামান্য সংশোধন করে, উপরের উত্তরটি সালিশি মাত্রার অ্যারে (1 ডি, 2 ডি, 3 ডি, ...) এর সাথে কাজ করে:
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()]
a[np.abs(a-a0).argmin)]
ঠিকভাবে কাজ করে.
a[np.sum(np.square(np.abs(a-a0)),1).argmin()]
।
উত্তরের সংক্ষিপ্তসার : যদি array
কারোর একটি বাছাই হয় তবে বাইসেশন কোড (নীচে দেওয়া) দ্রুততম সম্পাদন করে। বড় অ্যারেগুলির জন্য -1 100-1000 গুণ দ্রুত এবং ছোট অ্যারেগুলির জন্য -1 2-100 গুণ দ্রুত। এটির জন্য অদ্ভুতও দরকার নেই। যদি আপনার array
যদি অরসোর্টার্ড থাকে array
তবে বড় যদি হয় তবে প্রথমে একটি ও (এন লগন) বাছাই করে প্রথমে দ্বিখণ্ডিত ব্যবহার করা উচিত এবং যদি array
ছোট হয় তবে পদ্ধতি 2 দ্রুততম বলে মনে হয়।
প্রথমে আপনার নিকটতম মানের দ্বারা কী বোঝানো উচিত তা পরিষ্কার করা উচিত । প্রায়শই কেউ একটি অ্যাবসিসায় ব্যবধান চান, যেমন অ্যারে = [0,0.7,2.1], মান = 1.95, উত্তর হবে আইডিএক্স = 1 = এটি আমার ক্ষেত্রে সন্দেহ হয় যে আপনার প্রয়োজন (অন্যথায় আপনি বিরতিটি শোনার পরে নিম্নলিখিতগুলি ফলোআপ শর্তাধীন বিবৃতি দিয়ে খুব সহজেই সংশোধন করা যেতে পারে)। আমি লক্ষ করব যে এটি করার সর্বোত্তম উপায়টি দ্বিখণ্ডনের সাথে রয়েছে (যা আমি প্রথমে সরবরাহ করব - নোট করুন এটি মোটেও নিষ্প্রয়োজনের প্রয়োজন হয় না এবং নির্লিপ্ত ক্রিয়াকলাপগুলি ব্যবহার করার চেয়ে দ্রুততর কারণ তারা অপ্রয়োজনীয় ক্রিয়াকলাপগুলি সম্পাদন করে)। তারপরে আমি অন্যান্য ব্যবহারকারীদের দ্বারা এখানে উপস্থাপন করা অন্যদের বিরুদ্ধে সময়সীমা তুলনা করব।
দ্বিখণ্ডন:
def bisection(array,value):
'''Given an ``array`` , and given a ``value`` , returns an index j such that ``value`` is between array[j]
and array[j+1]. ``array`` must be monotonic increasing. j=-1 or j=len(array) is returned
to indicate that ``value`` is out of range below and above respectively.'''
n = len(array)
if (value < array[0]):
return -1
elif (value > array[n-1]):
return n
jl = 0# Initialize lower
ju = n-1# and upper limits.
while (ju-jl > 1):# If we are not yet done,
jm=(ju+jl) >> 1# compute a midpoint with a bitshift
if (value >= array[jm]):
jl=jm# and replace either the lower limit
else:
ju=jm# or the upper limit, as appropriate.
# Repeat until the test condition is satisfied.
if (value == array[0]):# edge cases at bottom
return 0
elif (value == array[n-1]):# and top
return n-1
else:
return jl
এখন আমি অন্যান্য উত্তরগুলি থেকে কোডটি সংজ্ঞায়িত করব, তারা প্রত্যেকে একটি সূচক ফেরত দেয়:
import math
import numpy as np
def find_nearest1(array,value):
idx,val = min(enumerate(array), key=lambda x: abs(x[1]-value))
return idx
def find_nearest2(array, values):
indices = np.abs(np.subtract.outer(array, values)).argmin(0)
return indices
def find_nearest3(array, values):
values = np.atleast_1d(values)
indices = np.abs(np.int64(np.subtract.outer(array, values))).argmin(0)
out = array[indices]
return indices
def find_nearest4(array,value):
idx = (np.abs(array-value)).argmin()
return idx
def find_nearest5(array, value):
idx_sorted = np.argsort(array)
sorted_array = np.array(array[idx_sorted])
idx = np.searchsorted(sorted_array, value, side="left")
if idx >= len(array):
idx_nearest = idx_sorted[len(array)-1]
elif idx == 0:
idx_nearest = idx_sorted[0]
else:
if abs(value - sorted_array[idx-1]) < abs(value - sorted_array[idx]):
idx_nearest = idx_sorted[idx-1]
else:
idx_nearest = idx_sorted[idx]
return idx_nearest
def find_nearest6(array,value):
xi = np.argmin(np.abs(np.ceil(array[None].T - value)),axis=0)
return xi
এখন আমি কোডগুলি সময় করব: নোট পদ্ধতিগুলি 1,2,4,5 সঠিকভাবে অন্তর দেয় না। পদ্ধতিগুলি অ্যারের নিকটস্থ বিন্দুতে 1,2,4 টি বৃত্তাকার (যেমন> = 1.5 -> 2), এবং পদ্ধতি 5 সর্বদা রাউন্ড আপ হয় (যেমন 1.45 -> 2)। কেবলমাত্র 3 এবং 6 পদ্ধতি এবং অবশ্যই দ্বিখণ্ডিতভাবে ব্যবধানটি সঠিকভাবে দেয়।
array = np.arange(100000)
val = array[50000]+0.55
print( bisection(array,val))
%timeit bisection(array,val)
print( find_nearest1(array,val))
%timeit find_nearest1(array,val)
print( find_nearest2(array,val))
%timeit find_nearest2(array,val)
print( find_nearest3(array,val))
%timeit find_nearest3(array,val)
print( find_nearest4(array,val))
%timeit find_nearest4(array,val)
print( find_nearest5(array,val))
%timeit find_nearest5(array,val)
print( find_nearest6(array,val))
%timeit find_nearest6(array,val)
(50000, 50000)
100000 loops, best of 3: 4.4 µs per loop
50001
1 loop, best of 3: 180 ms per loop
50001
1000 loops, best of 3: 267 µs per loop
[50000]
1000 loops, best of 3: 390 µs per loop
50001
1000 loops, best of 3: 259 µs per loop
50001
1000 loops, best of 3: 1.21 ms per loop
[50000]
1000 loops, best of 3: 746 µs per loop
একটি বৃহত অ্যারে দ্বিপক্ষীয় পরবর্তী সেরা 180us এবং দীর্ঘতম 1.21 মিমি (~ 100 - 1000 গুণ দ্রুত) এর তুলনায় 4us দেয়। ছোট অ্যারেগুলির জন্য এটি 2-100 গুন দ্রুত।
array
ছোট হয় তবে পদ্ধতি 2টিকে সবচেয়ে দ্রুত বলে মনে হয়।" আপনি @ জোশআলবার্ট বলতে কতটা ছোট?
ভেক্টরগুলির একটি অ্যারে নিকটতম ভেক্টরটি সন্ধানের জন্য এখানে একটি বর্ধিতকরণ রয়েছে।
import numpy as np
def find_nearest_vector(array, value):
idx = np.array([np.linalg.norm(x+y) for (x,y) in array-value]).argmin()
return array[idx]
A = np.random.random((10,2))*100
""" A = array([[ 34.19762933, 43.14534123],
[ 48.79558706, 47.79243283],
[ 38.42774411, 84.87155478],
[ 63.64371943, 50.7722317 ],
[ 73.56362857, 27.87895698],
[ 96.67790593, 77.76150486],
[ 68.86202147, 21.38735169],
[ 5.21796467, 59.17051276],
[ 82.92389467, 99.90387851],
[ 6.76626539, 30.50661753]])"""
pt = [6, 30]
print find_nearest_vector(A,pt)
# array([ 6.76626539, 30.50661753])
norm(..., axis=-1)
বের করার চেয়ে দ্রুত হওয়া উচিত x,y
। এছাড়াও, x,y
স্কেলারগুলি এখানে রয়েছে? তারপরে norm(x+y)
একটি বাগ রয়েছে, উদাহরণস্বরূপ, দূরত্বটি (+1, -1)
0 হিসাবে গণ্য হবে
idx = np.array([np.linalg.norm(x+y) for (x,y) in abs(array-value)]).argmin()
আপনি যদি নাম্পি ব্যবহার করতে না চান তবে এটি এটি করবে:
def find_nearest(array, value):
n = [abs(i-value) for i in array]
idx = n.index(min(n))
return array[idx]
এখানে এমন একটি সংস্করণ যা একটি স্কেলারবিহীন "মান" অ্যারে পরিচালনা করবে:
import numpy as np
def find_nearest(array, values):
indices = np.abs(np.subtract.outer(array, values)).argmin(0)
return array[indices]
অথবা ইনপুটটি যদি স্কেলার হয় তবে এমন একটি সংস্করণ যা কোনও সংখ্যার প্রকার (যেমন ইনট, ফ্লোট) ফেরত দেয়:
def find_nearest(array, values):
values = np.atleast_1d(values)
indices = np.abs(np.subtract.outer(array, values)).argmin(0)
out = array[indices]
return out if len(out) > 1 else out[0]
outer
ইউফুঙ্কের পদ্ধতিটি ব্যবহার করি নি, আমি মনে করি ভবিষ্যতে আরও ব্যবহার করব। প্রথম ফাংশনটি array[indices]
উপায় দ্বারা ফিরে আসা উচিত ।
np.subtract.outer
পুরো আউট-প্রোডাক্ট ম্যাট্রিক্স তৈরি করবে যা সত্যিই ধীর এবং মেমরি নিবিড় যদি array
এবং / অথবা values
খুব বড় হয়।
এখানে @Ari Onasafari, উত্তরের জন্য scipy সঙ্গে একটি সংস্করণ " ভেক্টর একটি অ্যারের মধ্যে নিকটতম ভেক্টর এটি "
In [1]: from scipy import spatial
In [2]: import numpy as np
In [3]: A = np.random.random((10,2))*100
In [4]: A
Out[4]:
array([[ 68.83402637, 38.07632221],
[ 76.84704074, 24.9395109 ],
[ 16.26715795, 98.52763827],
[ 70.99411985, 67.31740151],
[ 71.72452181, 24.13516764],
[ 17.22707611, 20.65425362],
[ 43.85122458, 21.50624882],
[ 76.71987125, 44.95031274],
[ 63.77341073, 78.87417774],
[ 8.45828909, 30.18426696]])
In [5]: pt = [6, 30] # <-- the point to find
In [6]: A[spatial.KDTree(A).query(pt)[1]] # <-- the nearest point
Out[6]: array([ 8.45828909, 30.18426696])
#how it works!
In [7]: distance,index = spatial.KDTree(A).query(pt)
In [8]: distance # <-- The distances to the nearest neighbors
Out[8]: 2.4651855048258393
In [9]: index # <-- The locations of the neighbors
Out[9]: 9
#then
In [10]: A[index]
Out[10]: array([ 8.45828909, 30.18426696])
@ দিমিত্রি এর সমাধানের একটি দ্রুত ভেক্টরাইজড সংস্করণ এখানে যদি আপনার values
সন্ধানের জন্য অনেকগুলি থাকে ( values
বহুমাত্রিক অ্যারে হতে পারে):
#`values` should be sorted
def get_closest(array, values):
#make sure array is a numpy array
array = np.array(array)
# get insert positions
idxs = np.searchsorted(array, values, side="left")
# find indexes where previous index is closer
prev_idx_is_less = ((idxs == len(array))|(np.fabs(values - array[np.maximum(idxs-1, 0)]) < np.fabs(values - array[np.minimum(idxs, len(array)-1)])))
idxs[prev_idx_is_less] -= 1
return array[idxs]
benchmarks
> for
@ ডেমিট্রির সমাধান` দিয়ে একটি লুপ ব্যবহারের চেয়ে 100 গুণ বেশি দ্রুত `
>>> %timeit ar=get_closest(np.linspace(1, 1000, 100), np.random.randint(0, 1050, (1000, 1000)))
139 ms ± 4.04 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
>>> %timeit ar=[find_nearest(np.linspace(1, 1000, 100), value) for value in np.random.randint(0, 1050, 1000*1000)]
took 21.4 seconds
idx = np.searchsorted(array, values)
তারপরে idx[array[idx] - values>np.diff(array).mean()*0.5]-=1
এবং অবশেষেreturn array[idx]
বড় অ্যারেগুলির জন্য, @ দিমিত্রি প্রদত্ত (দুর্দান্ত) উত্তরটি বর্তমানে সেরা হিসাবে চিহ্নিত হিসাবে উত্তরের চেয়ে অনেক দ্রুত। আমি তার সঠিক অ্যালগরিদম নিম্নলিখিত দুটি উপায়ে মানিয়ে নিয়েছি:
ইনপুট অ্যারে বাছাই করা আছে কিনা নীচের ফাংশনটি কাজ করে।
নীচের ফাংশনটি নিকটতম মান অনুসারে ইনপুট অ্যারের সূচকটি প্রদান করে যা কিছুটা সাধারণ।
নোট করুন যে নীচের ফাংশনটি একটি নির্দিষ্ট প্রান্ত কেস পরিচালনা করে যা @ ডিমেট্রি দ্বারা লিখিত মূল ফাংশনে একটি বাগ তৈরি করতে পারে। অন্যথায়, আমার অ্যালগরিদম তার অনুরূপ।
def find_idx_nearest_val(array, value):
idx_sorted = np.argsort(array)
sorted_array = np.array(array[idx_sorted])
idx = np.searchsorted(sorted_array, value, side="left")
if idx >= len(array):
idx_nearest = idx_sorted[len(array)-1]
elif idx == 0:
idx_nearest = idx_sorted[0]
else:
if abs(value - sorted_array[idx-1]) < abs(value - sorted_array[idx]):
idx_nearest = idx_sorted[idx-1]
else:
idx_nearest = idx_sorted[idx]
return idx_nearest
x = np.array([2038, 1758, 1721, 1637, 2097, 2047, 2205, 1787, 2287, 1940, 2311, 2054, 2406, 1471, 1460])
। সঙ্গে find_nearest(x, 1739.5)
(প্রথম সমাংশক নিকটস্থ মান), আমি পেতে 1637
(যুক্তিসঙ্গত) এবং 1
(বাগ?)।
এটি আনটবুর উত্তরের একটি ভেক্টরাইজড সংস্করণ :
def find_nearest(array, values):
array = np.asarray(array)
# the last dim must be 1 to broadcast in (array - values) below.
values = np.expand_dims(values, axis=-1)
indices = np.abs(array - values).argmin(axis=-1)
return array[indices]
image = plt.imread('example_3_band_image.jpg')
print(image.shape) # should be (nrows, ncols, 3)
quantiles = np.linspace(0, 255, num=2 ** 2, dtype=np.uint8)
quantiled_image = find_nearest(quantiles, image)
print(quantiled_image.shape) # should be (nrows, ncols, 3)
আমি মনে করি সবচেয়ে পাইথোনিক উপায়টি হ'ল:
num = 65 # Input number
array = n.random.random((10))*100 # Given array
nearest_idx = n.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)
এটি মৌলিক কোড। আপনি চাইলে এটি একটি ফাংশন হিসাবে ব্যবহার করতে পারেন
দক্ষ কোড লিখতে তথ্য সংগ্রহ করার জন্য সমস্ত উত্তর উপকারী। তবে আমি বিভিন্ন ক্ষেত্রে অপ্টিমাইজ করতে একটি ছোট পাইথন স্ক্রিপ্ট লিখেছি। প্রদত্ত অ্যারে বাছাই করা থাকলে এটি সেরা ক্ষেত্রে হবে। যদি কোনও নির্দিষ্ট মানের নিকটতম বিন্দুর সূচকটি সন্ধান করে তবে bisect
মডিউলটি সবচেয়ে বেশি সময় দক্ষ। যখন একটি অনুসন্ধান সূচকগুলি একটি অ্যারের সাথে মিলে যায়, তখন 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)
[]৩]:% সময় বিসেক্ট.বিসেক্ট_সামগ্রী (এক্সলিস্ট, ০.০) সিপিইউ বার: ব্যবহারকারী 0 এনএস, সিএস: 0 এনএস, মোট: 0 এনএস ওয়াল সময়: 22.2 µ সে
np.searchsorted(xar, 0.3, side="left")
[]৪] ইন:% সময় এনপি.সর্চসোর্টড (xar, 0.3, পাশ = "বাম") সিপিইউ বার: ব্যবহারকারী 0 এনএস, সিএস: 0 এনএস, মোট: 0 এনএস ওয়াল সময়: 98.9 µ সে
randpts = np.random.rand(1000)
np.searchsorted(xar, randpts, side="left")
% টাইম এনপি.সার্চসোর্টড (এক্সার, র্যান্ডপেটস, সাইড = "বাম") সিপিইউ বার: ব্যবহারকারী 4 এমএস, সিএস: 0 এনএস, মোট: 4 এমএস ওয়াল টাইম: 1.2 এমএস
আমরা যদি গুণক নিয়মটি অনুসরণ করি, তবে নিম্পিকে ~ 100 এমএস নেওয়া উচিত যা ~ 83X দ্রুত বোঝায়।
2 ডি অ্যারের জন্য, নিকটতম উপাদানটির i, j অবস্থান নির্ধারণ করতে:
import numpy as np
def find_nearest(a, a0):
idx = (np.abs(a - a0)).argmin()
w = a.shape[1]
i = idx // w
j = idx - i * w
return a[i,j], i, j
import numpy as np
def find_nearest(array, value):
array = np.array(array)
z=np.abs(array-value)
y= np.where(z == z.min())
m=np.array(y)
x=m[0,0]
y=m[1,0]
near_value=array[x,y]
return near_value
array =np.array([[60,200,30],[3,30,50],[20,1,-50],[20,-500,11]])
print(array)
value = 0
print(find_nearest(array, value))
এর জন্য উপকারী হতে পারে ndarrays
:
def find_nearest(X, value):
return X[np.unravel_index(np.argmin(np.abs(X - value)), X.shape)]
return np.abs(array-value).min()
ভুল উত্তর দেয়। এটি আপনাকে পরম মানের দূরত্বের মিনিট দেয় এবং কোনওভাবে আমাদের আসল অ্যারের মানটি ফেরত দিতে হবে। আমরা যোগ করতেvalue
এবং কাছে আসতে পারতাম , তবে পরম মানটি জিনিসগুলিতে একটি রেঞ্চ ফেলে দেয় ...