繁体   English   中英

在 python 列表中查找相似条目

[英]Finding similar entries in python lists

我有 2 个元组列表list1 = [(1.332, 3.23344, 3.22), (2.122, 2.11, 2.33), ... (1, 2, 3)]list2 = [(4.23, 12.2, 3.333), (1.234, 3.21, 4.342), ... (1.1, 2.2, 3.3)] 这些列表都很长,两个列表都有数百万。 就上下文而言,这些数据点中的每一个都是 position 在两个不同数据集中的某种度量。 现在我想将list1中的每个条目对应到list2中的一个条目,如果它“足够接近”的话。 足够接近是指位置之间的距离小于某个阈值(例如 1)。 我最初的想法是在list1的每个条目上使用min function 。 也就是说,以下内容:

import numpy as np
import random

def dist(pt1, pt2): 
    return np.sqrt( ((pt2[0] - pt1[0]) ** 2) + ((pt2[1] - pt1[1]) ** 2) + ((pt2[2] - pt1[2]) ** 2) ) 

list1 = [(random.random(), random.random(), random.random()) for _ in range(25)]                                                                                              

list2 = [(random.random(), random.random(), random.random()) for _ in range(20)]   

threshold = .5
linker = []
for i, entry in enumerate(list1): 
    m = min(list2, key=lambda x: dist(entry, x)) 
    if dist(entry, m) < threshold: 
         linker.append((i, list2.index(m))

因此,这会将list1中的每个索引链接到list2中的索引。 但我觉得必须有一些专门针对这个任务开发的算法,它要快得多,是吗?

您正在查找数据集中每个点与第二个数据集的最近邻。

  1. 您发布的方法具有复杂性 O(N^2)
  2. 由于 N ~ 100 万,这变得站不住脚。

对于大型数据集, 最近邻方法要好得多,因为它们的复杂度为 O(N*log(N))

Python 中两个流行的是KDTree 和 BallTree

用 BallTree 解决这个问题的一个例子

sklearn BallTree 文档

import numpy as np
from sklearn.neighbors import BallTree

# Generate Dataset 1 (random positions in 3D)
rng = np.random.RandomState(0)
X = rng.random_sample((10, 3))  # 10 points in 3 dimensions

# Setup nearest neighbor tree  for dataset 1
# to process nearest neighbor queries
tree = BallTree(X, leaf_size=2)

# Generate Dataset 2 (random positions in 3D)
Y = rng.random_sample((10, 3))

# For each point in Dataset 2
# find the index and distance to the closest 
# point in Dataset 1 (using the nearest neighbor tree
# for dataset 1)
dist, ind = tree.query(Y, k=1)  # nearest neighbor  

# Results
for i, (ind, d) in enumerate(zip(ind, dist)):
  print(f'Y index {i}, closest index X is {ind}, dist {d}')

Output

Y index 0, closest index X is [3], dist [0.14046915]
Y index 1, closest index X is [1], dist [0.40653272]
Y index 2, closest index X is [7], dist [0.29291477]
Y index 3, closest index X is [1], dist [0.25785655]
Y index 4, closest index X is [1], dist [0.39477652]
Y index 5, closest index X is [9], dist [0.50373484]
Y index 6, closest index X is [1], dist [0.24894356]
Y index 7, closest index X is [4], dist [0.14716665]
Y index 8, closest index X is [5], dist [0.25875381]
Y index 9, closest index X is [8], dist [0.24204497]

是的,绝对这是一种耗时的方法,因为首先 python 没有针对这些计算进行优化(针对数据类型等),其次这些计算需要在任何语言中进行优化。 您必须使用库来操作矩阵,例如 numpy 和 pandas。 for example in your case i recommend this solution: first: convert your data to a dataframe of pandas like this post: List of Tuples to DataFrame Conversion second: after that conversion with pandas this is a routin and easy calculation. 例如: https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.pow.ZFC35FDC70D5FC69D2698Z83A822C7A5E3

pandas 使用 numpy 和 numpy 针对这些计算进行了优化。

一个简单的解决方案是保留一个 3d 单元格数组,以将您的条目分组。 例如, (1.332, 3.23344, 3.22)可能被分组到单元格(13, 32, 32)中。 打包该数据结构后,您可以通过查看(13, 32, 32) (及其 26 个邻居的某个子集)找到(1.332, 3.23344, 3.22)附近的所有点。

如果你真的需要这个速度很快,你就会进入一组称为“空间分区器”的算法。 您可能会研究一种称为“kd-tree”的东西,它非常适合以超紧凑的方式存储点的非均匀分布(并且针对检索某个位置的邻域中的点进行了优化。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM