Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在对象中保留坐标时,在python中使用kd树查找k个最近邻_Python_Python 3.x_Scipy_Nearest Neighbor_Kdtree - Fatal编程技术网

在对象中保留坐标时,在python中使用kd树查找k个最近邻

在对象中保留坐标时,在python中使用kd树查找k个最近邻,python,python-3.x,scipy,nearest-neighbor,kdtree,Python,Python 3.x,Scipy,Nearest Neighbor,Kdtree,我需要从集合中找到每个对象的k最近邻。每个对象都有其坐标作为属性。 为了解决这个任务,我尝试使用scipy中的spatial.KDTree。如果我使用列表或元组来表示一个点,它可以很好地工作,但它不适用于对象。 我在我的类中实现了\uuuuu getitem\uuuuuuuuuuuuuuuuuu和len\uuuuuuuuuuuuuu方法,但是KDTree实现要求我的对象提供不存在的坐标轴(比如二维点的三维坐标) 以下是重现问题的简单脚本: 从scipy导入空间 班级单位: 定义初始化(self,

我需要从集合中找到每个对象的
k
最近邻。每个对象都有其坐标作为属性。 为了解决这个任务,我尝试使用
scipy
中的
spatial.KDTree
。如果我使用列表或元组来表示一个点,它可以很好地工作,但它不适用于对象。 我在我的类中实现了
\uuuuu getitem\uuuuuuuuuuuuuuuuuu
len\uuuuuuuuuuuuuu
方法,但是
KDTree
实现要求我的对象提供不存在的坐标轴(比如二维点的三维坐标)

以下是重现问题的简单脚本:

从scipy导入空间
班级单位:
定义初始化(self,x,y):
self.x=x
self.y=y
定义uu获取项目uu(自身,索引):
如果索引==0:
返回self.x
elif索引==1:
回归自我
其他:
引发异常('单位坐标为二维')
定义(自我):
返回2
#分数=[(1,1)、(2,2)、(3,3)、(4,4)、(5,5)]
#点数=[[1,1]、[2,2]、[3,3]、[4,4]、[5,5]]
分数=[单位(1,1)、单位(2,2)、单位(3,3)、单位(4,4)、单位(5,5)]
树=空间.KDTree(点)
#result=tree.query((6,6),3)
结果=树。查询(单位(6,6),3)
打印(结果)
我不需要使用这个特定的实现或库,甚至算法,但需要处理对象


另外,我可以向每个对象添加
id
字段,并将所有坐标移动到单独的数组中,其中索引为object
id
。但是如果可能的话,我仍然希望避免这种方法。

类可能需要访问对象的切片。但是根据您的定义,不可能使用切片(尝试
Unit(6,6)[:]
,它将抛出相同的错误)

处理此问题的一种方法是将x和y变量保存在列表中:

类单位:
定义初始化(self,x,y):
self.x=x
self.y=y
self.data=[x,y]
定义uu获取项目uu(自身,索引):
返回self.data[索引]
定义(自我):
返回2
分数=[单位(1,1)、单位(2,2)、单位(3,3)、单位(4,4)、单位(5,5)]
树=空间.KDTree(点)
结果=树。查询(单位(6,6),3)
打印(结果)
for
scipy.spatial.KDTree
说明
data
参数应该是
array\u like
,这通常意味着“可转换为numpy数组”。实际上,初始化的第一行尝试将数据转换为numpy数组,如图中所示:

类KDTree(对象):
""" ... """
def uuu init_uuu(self,data,leafsize=10):
self.data=np.asarray(数据)
因此,您想要实现的是一个对象,以便它们的列表可以很好地转换为numpy数组。这是因为numpy尝试了多种方法将对象生成数组。但是,包含许多相同长度序列的iterable肯定是合格的

您的
单元
对象基本上是一个序列,因为它实现了
\uuuu len\uuuu
\uuuu getitem\uuuu
以及从0开始的顺序整数索引。Python知道序列何时结束,并点击
索引器。但是您的
\uuu getitem\uu
会在错误索引上引发
异常。因此,从这两种方法提供顺序迭代的正常机制中断了。相反,请引发一个
索引器
,您将很好地转换:

类单位:
定义初始化(self,x,y):
self.x=x
self.y=y
定义uu获取项目uu(自身,索引):
如果索引==0:
返回self.x
elif索引==1:
回归自我
升起索引器('单位坐标为二维')
定义(自我):
返回2
现在,我们可以检查这些转换为numpy数组的列表,没有问题:

[5]中的
:np.数组([单元(1,1),单元(2,2),单元(3,3),单元(4,4),单元(5,5)])
出[5]:
数组([[1,1],
[2, 2],
[3, 3],
[4, 4],
[5, 5]])
因此,现在初始化
KDTree
应该没有问题。这就是为什么如果您将coords存储在一个内部列表中,然后将
\uuuu getitem\uuuu
延迟到该列表中,或者简单地将coords视为一个简单的序列,如列表或元组,您就可以了


对于像这样的简单类,一种更简单的方法是使用
namedtuples
或类似的方法,但是对于更复杂的对象,将它们转换为序列是一种很好的方法。

根据文档,数据应该是类似数组的——这可能意味着不仅可以索引,而且可以索引。我相信
\uuu getitem\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?大概它只是获取数据并尝试将其转换为numpy数组。编辑:是的,这是一个很好的答案。使用namedtuples有什么想法?在getitem?@crypdick namedtuples中,元组是元组,因此它们已经是序列了——不需要在它们上面定义
\uuuuuu getitem\uuu
。如果将上述代码中的类定义替换为
Unit=namedtuple(“Unit”,“x,y”)
,那么它就可以正常工作。
(array([1.41421356, 2.82842712, 4.24264069]), array([4, 3, 2]))