Python 搜索numpy数组((x,y,z)…)以查找与最近的x,y匹配的z
我有一个非常大的数组,类似于以下格式的高程数据:Python 搜索numpy数组((x,y,z)…)以查找与最近的x,y匹配的z,python,numpy,scipy,interpolation,Python,Numpy,Scipy,Interpolation,我有一个非常大的数组,类似于以下格式的高程数据: triplets = ((x0, y0, z0), (x1, y1, z1), ... , (xn, yn, zn)) 其中x,y,z都是以米为单位的浮点数。您可以创建与此格式相匹配的合适测试数据: x = np.arange(20, 40, dtype=np.float64) y = np.arange(30, 50, dtype=np.float64) z = np
triplets = ((x0, y0, z0),
(x1, y1, z1),
... ,
(xn, yn, zn))
其中x,y,z都是以米为单位的浮点数。您可以创建与此格式相匹配的合适测试数据:
x = np.arange(20, 40, dtype=np.float64)
y = np.arange(30, 50, dtype=np.float64)
z = np.random.random(20) * 25.0
triplets = np.hstack((x, y, z)).reshape((len(x),3))
我希望能够有效地找到给定(x,y)对对应的z值。到目前为止,我的研究引出了更多的问题。以下是我得到的:
query = (a, b) # where a, b are the x and y coordinates we're looking for
for i in triplets:
if i[0] == query[0] and i[1] == query[1]:
result = i[2]
缺点:速度慢<代码>a、b必须存在,这是比较浮动的问题points = triplets[:,0:2] # drops the z column
tree = cKDTree(points)
idx = tree.query((a, b))[1] # this returns a tuple, we want the index
query = tree.data[idx]
result = triplets[idx, 2]
缺点:返回最近点而不是插值f = interp2d(x, y, z)
result = f(a, b)
缺点:不适用于大型数据集。我得到了溢出错误:在实际数据上运行时,需要插入的数据点太多。(我的真实数据约为1100万点。)所以问题是:有没有我忽略的简单方法?有没有办法减少上述缺点 您可以创建稀疏矩阵并使用简单的索引
In [1]: import numpy as np
In [2]: x = np.arange(20, 40, dtype=np.float64)
In [3]: y = np.arange(30, 50, dtype=np.float64)
In [4]: z = np.random.random(20) * 25.0
In [9]: from scipy.sparse import coo_matrix
In [12]: m = coo_matrix((z, (x, y))).tolil()
In [17]: m[25,35]
Out[17]: 17.410532044604292
我不明白你的cKDTree代码,你得到了
idx
,为什么再次执行for循环?您只需通过result=triplets[idx,2]
即可获得结果
from scipy.spatial import cKDTree
x = np.arange(20, 40, dtype=np.float64)
y = np.arange(30, 50, dtype=np.float64)
z = np.random.random(20) * 25.0
triplets = np.hstack((x, y, z)).reshape((len(x),3))
a = 30.1
b = 40.5
points = triplets[:,0:2] # drops the z column
tree = cKDTree(points)
idx = tree.query((a, b))[1] # this returns a tuple, we want the index
result = triplets[idx, 2]
如果你想插入结果,而不是只为最近的邻居找到Z值,我会考虑做如下的事情:
import numpy as np
from scipy.spatial import cKDTree
# some fake (x, y, z) data
XY = np.random.rand(10000, 2) - 0.5
Z = np.exp(-((XY ** 2).sum(1) / 0.1) ** 2)
# construct a k-d tree from the (x, y) coordinates
tree = cKDTree(XY)
# a random point to query
xy = np.random.rand(2) - 0.5
# find the k nearest neighbours (say, k=3)
distances, indices = tree.query(xy, k=3)
# the z-values for the k nearest neighbours of xy
z_vals = Z[indices]
# take the average of these z-values, weighted by 1 / distance from xy
dw_avg = np.average(z_vals, weights=(1. / distances))
值得玩玩一下k值,k是最近邻居的平均数。这本质上是一种粗糙的形式,其中k值控制着对z值的基本分布施加的“平滑度”。k越大,平滑度越高
类似地,您可能希望根据点与(xi,yi)的距离来权衡点的贡献,这取决于您认为z中的相似性如何随着x,y距离的增加而减少。例如,您可能希望通过(1/距离**2)
而不是(1/距离)
来加权
在性能方面。请记住,您只需要为数据集构建一次树,如果需要,您可以通过将(N,2)数组传递到tree.query()
,一次查询多个点
用于近似近邻搜索的工具(例如)可能更快,但在数据维数非常高的情况下,这些工具通常更有用。创建一个以
(x,y)
形式的元组作为键,映射到z
值的字典是否可行?这将使查找时间保持不变,生成词典的前期成本很大,并且可能会严重影响内存使用。您需要这个吗?除非你事先知道你的钥匙。假设您的输入数据有一个(20.05,45.0,5.55)。我们用foo[(20.05,45.0)]=5.55将其分配到dict中。当你试图查询你的dictfoo[(20,45)]
时,你会得到一个KeyError
。我想要的是返回最近点的值,或者更好的是,一个从附近点得到的插值。正如你所说,你有三组数据。是否可以使用类似的方式将它们表示为三个2D字段,然后进行2D插值?(这可能只有在z值非常平滑的情况下才能很好地工作)对于大型数据集,我怀疑任何东西都比不上cKDTree。这是一个好主意,但是,它不能可靠地工作!我运行了您提供的代码,对于某些值,它返回预期的结果。对于其他人,它返回0。例如,对于m[25,35]
来说,它是有效的,就像m[25.1,35.999]
一样。但是,对于m[25,36]
我什么也得不到。好的,问题在于浮点值。因此,您可以为x和y值创建索引。例如,您可以从数组席、Y和Z创建矩阵M。席和彝是X和Y中的项目位置向量。您可以创建一个DICT,将值从x转换为席,或者预X,然后使用某种类型的二进制搜索来查找项目的索引。我已经更新了。谢谢