【问题标题】:In python, what is a good way to match expected values to real values?在 python 中,将期望值与实际值匹配的好方法是什么?
【发布时间】:2015-06-13 18:54:06
【问题描述】:

给定一个具有理想 x,y 位置的字典,我有一个接近理想位置的无序真实 x,y 位置列表,我需要将它们分类到相应的理想位置字典键。有时,对于给定位置,我根本没有得到任何数据 (0,0)。 一个示例数据集是:

idealLoc= {1:(907,1026),
           2:(892,1152),
           3:(921,1364),
           4:(969,1020),
           5:(949,1220),
           6:(951,1404),
   'No_Data':(0,0)}

realLoc = [[  892.,  1152.],
           [  969.,  1021.],
           [  906.,  1026.],
           [  949.,  1220.],
           [  951.,  1404.],
           [    0.,     0.]]

输出将是一个新字典,其真实位置分配给来自idealLoc 的正确字典键。我已经考虑过蛮力方法(为每个最佳匹配扫描整个列表 n 次),但我想知道是否有更优雅/更有效的方法?

编辑:下面是“蛮力”方法

Dest = {}
dp = 6
for (y,x) in realLoc:
    for key, (r,c) in idealLoc.items():   
        if x > c-dp and x < c+dp and y > r-dp and y < r+dp:
            Dest[key] = [y,x]
            break

【问题讨论】:

  • 你看过itertools.starmap吗?它不会很快,但是您可以编写映射函数来计算真实坐标和理想坐标之间的距离并返回最接近理想坐标的键。

标签: python numpy classification


【解决方案1】:

K-d trees 是一种高效的数据分区方式,可以执行快速的最近邻搜索。您可以使用scipy.spatial.cKDTree 来解决您的问题,如下所示:

import numpy as np
from scipy.spatial import cKDTree

# convert inputs to numpy arrays
ilabels, ilocs = (np.array(vv) for vv in zip(*idealLoc.iteritems()))
rlocs = np.array(realLoc)

# construct a K-d tree that partitions the "ideal" points
tree = cKDTree(ilocs)

# query the tree with the real coordinates to find the nearest "ideal" neigbour
# for each "real" point
dist, idx = tree.query(rlocs, k=1)

# get the corresponding labels and coordinates
print(ilabels[idx])
# ['2' '4' '1' '5' '6' 'No_Data']

print(ilocs[idx])
# [[ 892 1152]
#  [ 969 1020]
#  [ 907 1026]
#  [ 949 1220]
#  [ 951 1404]
#  [   0    0]]

默认情况下cKDTree 使用欧几里得范数作为距离度量,但您也可以通过将p= 关键字参数传递给tree.query() 来指定曼哈顿范数、最大范数等。

还有scipy.interpolate.NearestNDInterpolator 类,它基本上只是scipy.spatial.cKDTree 的便捷包装器。

【讨论】:

  • 谢谢阿里。我在一个稍微大一点的数组上运行了这段代码,它对我不起作用......我得到了以下结果: ilabels[idx]= [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1] 和 ilocs[ idx]=[[ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [ 907 1026] [907 1026] 1026] [ 907 1026] [ 907 1026] [ 907 1026]]
  • 那么,您的输入数据是什么样的?在每个“真实”输入点比任何其他“理想”点更接近(907, 1026) 的情况下,这是一个完全合理的结果。
  • 事实上,可能发生的事情是{1:(907, 1026)} 是最接近(0, 0) 的“理想”位置,因此在您没有数据并使用(0, 0) 进行查询的每种情况下,您将匹配第 1 点。您可能希望在您的 idealloc 字典中添加类似这样的内容:{"no_data":(0, 0)} 来处理此类情况。
【解决方案2】:

假设你想使用欧式距离,你可以使用scipy.spatial.distance.cdist计算距离矩阵,然后选择最近的点。

import numpy
from scipy.spatial import distance

ideal = numpy.array(idealloc.values())
real = numpy.array(realloc)

dist = distance.cdist(ideal, real)

nearest_indexes = dist.argmin(axis=0)

【讨论】:

    猜你喜欢
    • 2021-11-28
    • 2020-06-12
    • 2018-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-14
    • 2021-02-28
    • 1970-01-01
    相关资源
    最近更新 更多