Python 为另一个数组中的所有浮点查找数组中最近的浮点
根据在另一个数组中找到的最接近的浮点值“过滤”数组时出现性能问题 这是问题的Python 为另一个数组中的所有浮点查找数组中最近的浮点,python,arrays,performance,algorithm,numpy,Python,Arrays,Performance,Algorithm,Numpy,根据在另一个数组中找到的最接近的浮点值“过滤”数组时出现性能问题 这是问题的MWE: import numpy as np def random_data(N): # Generate some random data. return np.random.uniform(0., 10., N).tolist() # Data lists. N1 = 1500 list1 = [random_data(N1), random_data(N1), random_data(N1)]
MWE
:
import numpy as np
def random_data(N):
# Generate some random data.
return np.random.uniform(0., 10., N).tolist()
# Data lists.
N1 = 1500
list1 = [random_data(N1), random_data(N1), random_data(N1)]
list2 = random_data(1000)
# Define list1's range.
min_1, max_1 = min(list1[2]), max(list1[2])
# This list will contain the "filtered" list1.
list4 = [[], [], []]
# Go through each element in list2.
for elem2 in list2:
# If it is located within the list1 range.
if min_1 <= elem2 <= max_1:
# Find the closest float in sub-list list1[2] to this float
# in list2.
indx, elem1 = min(enumerate(list1[2]), key=lambda x:abs(x[1]-elem2))
# Store the values in list1 that are associated with the closest float
# found above.
list4[0].append(list1[0][indx])
list4[1].append(list1[1][indx])
list4[2].append(elem1)
现在list1[2]
的范围不等于list2
的范围,因此给出的答案无法拒绝那些i
最大值(list1[2])或list2[i]
的点
可以修改这个答案来考虑这种可能性吗?我很抱歉这样更改了原始代码,我真的错过了。如果您有SciPy,a可以完成这项工作:
import numpy
import scipy.spatial
array1 = numpy.array(list1)
array2 = numpy.array(list2)
# A tree optimized for nearest-neighbor lookup
tree = scipy.spatial.cKDTree(array1[2, ..., numpy.newaxis])
# The distances from the elements of array2 to their nearest neighbors in
# array1, and the indices of those neighbors.
distances, indices = tree.query(array2[..., numpy.newaxis])
array4 = array1[:, indices]
k-d树是为多维数据而设计的,因此这可能不是最快的解决方案,但与现有的解决方案相比,它应该非常快。k-d树期望以点的2D数组的形式输入,其中,data[i]
是一个1D数组,表示i
th点,因此使用带有newaxis
的切片表达式将数据放入该格式。如果您需要更快的速度,您可以使用numpy.sort
和numpy.searchsorted
进行操作
如果需要拒绝list2
中超出list1[2]
给定值范围的数据,可通过预处理步骤完成:
lowbound = array1[2].min()
highbound = array1[2].max()
querypoints = array2[(array2 >= lowbound) & (array2 <= highbound)]
distances, indices = tree.query(querypoints[..., numpy.newaxis])
lowbound=array1[2].min()
上限=阵列1[2]。最大值()
querypoints=array2[(array2>=lowbound)&(array2Kd-tree在这里真是太过分了,你需要做的就是对数组进行排序,并使用二进制搜索在排序后的数组中找到最接近的值。我不久前写过一篇文章,讲述了如何使用searchsorted
找到数组中目标的密室值。你可以在这里使用相同的想法:
import numpy as np
def find_closest(A, target):
#A must be sorted
idx = A.searchsorted(target)
idx = np.clip(idx, 1, len(A)-1)
left = A[idx-1]
right = A[idx]
idx -= target - left < right - target
return idx
def random_data(shape):
# Generate some random data.
return np.random.uniform(0., 10., shape)
def main(data, target):
order = data[2, :].argsort()
key = data[2, order]
target = target[(target >= key[0]) & (target <= key[-1])]
closest = find_closest(key, target)
return data[:, order[closest]]
N1 = 1500
array1 = random_data((3, N1))
array2 = random_data(1000)
array2[[10, 20]] = [-1., 100]
array4 = main(array1, array2)
将numpy导入为np
def find_最接近(A,目标):
#A必须分类
idx=A.searchsorted(目标)
idx=np.clip(idx,1,len(A)-1)
左=A[idx-1]
右=A[idx]
idx-=目标-左<右-目标
返回idx
def随机_数据(形状):
#生成一些随机数据。
返回np.随机均匀(0,10.,形状)
def主(数据、目标):
订单=数据[2,:]。argsort()
键=数据[2,顺序]
target=target[(target>=key[0])&(target这可能属于codereview…但为什么不对列表1[2]进行2c排序,然后将min1、max1分别排序为[0]
和[-1]
…这将使您可以使用二进制搜索更快地找到最近的值…Ithink@JoranBeasley与O(N)相比,排序为O(NlogN)
min
、max
所花费的时间。因此,min
和max
在这里会更快(至少在理论上)。二进制搜索在这里不起作用,因为OP正在寻找具有最小绝对差异的项的索引。好吧,公平点…他似乎仍然能够在排序列表中更快地找到abs差异…并可能节省足够的时间使排序值得…也许…二进制搜索可以找到最小绝对差异,没有问题。这将返回一个错误:ValueError:需要多个值才能解包tree=scipy.spatial.KDTree(array1[2])
行中的。您可以在此处测试:)好的,已经修复并测试。理论上,它应该可以工作。但是可能需要更多的解释。@Gabriel:还不够?我想KD树实现的开销抵消了更好的渐进运行时带来的许多好处。我将尝试使用numpy.digitalize
编写一些东西,看看是否效果更好。scipy.spatial.cKDTree wi我很可能会给你增加10倍。注意这里额外的“c”。k-d树确实有些过头了。我之所以选择它,是因为它提供了一个方便的界面,而且比我选择searchsorted
;searchsorted
或类似的东西的机会要小得多,因为如果k-d树太慢的话,备份计划是这样做的。惊人的答案,甚至比用户2357112给出的答案还要快!我不明白最后一行array2[[10,20]]=[-1,100]
,你这样做是为了什么?它取代了array[10]
和array[20]
使用-1和100。它们在那里,因此我可以检查结果并确保这些值被拒绝。如果我使用了您第二次更新中的代码,我就不需要这一行了。太好了,我现在看到了替换的必要性。我选择这个答案是因为它比user2357112的答案提高了~3倍的速度。非常感谢你们伙计们!
import numpy as np
def find_closest(A, target):
#A must be sorted
idx = A.searchsorted(target)
idx = np.clip(idx, 1, len(A)-1)
left = A[idx-1]
right = A[idx]
idx -= target - left < right - target
return idx
def random_data(shape):
# Generate some random data.
return np.random.uniform(0., 10., shape)
def main(data, target):
order = data[2, :].argsort()
key = data[2, order]
target = target[(target >= key[0]) & (target <= key[-1])]
closest = find_closest(key, target)
return data[:, order[closest]]
N1 = 1500
array1 = random_data((3, N1))
array2 = random_data(1000)
array2[[10, 20]] = [-1., 100]
array4 = main(array1, array2)