查找数据集中所有点距离最近的点 - Python

2024-04-13

我有一个数据集如下,

Id     Latitude      longitude
1      25.42         55.47
2      25.39         55.47
3      24.48         54.38
4      24.51         54.54

我想找到数据集每个点的最近距离。我在互联网上找到了以下距离函数,

from math import radians, cos, sin, asin, sqrt
def distance(lon1, lat1, lon2, lat2):
    """
    Calculate the great circle distance between two points 
    on the earth (specified in decimal degrees)
    """
    # convert decimal degrees to radians 
    lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
    # haversine formula 
    dlon = lon2 - lon1 
    dlat = lat2 - lat1 
    a = sin(dlat/2)**2 + cos(lat1) * cos(lat2) * sin(dlon/2)**2
    c = 2 * asin(sqrt(a)) 
    km = 6367 * c
    return km

我正在使用以下功能,

shortest_distance = []
for i in range(1,len(data)):
    distance1 = []
    for j in range(1,len(data)):
        distance1.append(distance(data['Longitude'][i], data['Latitude'][i], data['Longitude'][j], data['Latitude'][j]))
    shortest_distance.append(min(distance1))

但此代码对每个条目循环两次并返回 n^2 次迭代,因此速度非常慢。我的数据集包含近 100 万条记录,每次循环所有元素两次变得非常昂贵。

我想找到更好的方法来找出每一行的最近点。有人能帮我找到一种方法来解决这个问题吗?

Thanks


寻找最近的蛮力方法N指向给定点的点是O(N)——你必须检查每一点。 相反,如果N点存储在KD-tree https://en.wikipedia.org/wiki/K-d_tree,然后求最近点的平均值O(log(N))。 构建 KD 树还需要额外的一次性成本,这需要O(N) time.

如果您需要重复此过程N次,那么暴力法就是O(N**2)kd树方法是O(N*log(N))。 因此,对于足够大的N,KD树将击败暴力法。

See here http://scikit-learn.org/stable/modules/neighbors.html#nearest-neighbor-algorithms有关最近邻算法(包括 KD 树)的更多信息。


下面(在函数中using_kdtree) 是一种计算最近邻的大圆弧长的方法scipy.spatial.kdtree https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.spatial.KDTree.html.

scipy.spatial.kdtree使用点之间的欧几里得距离,但是有一个formula https://en.wikipedia.org/wiki/Great-circle_distance#From_chord_length用于将球体上各点之间的欧几里得弦距离转换为大圆弧长(给定球体的半径)。 所以想法是将纬度/经度数据转换为笛卡尔坐标,使用KDTree找到最近的邻居,然后应用大圆距离公式 https://en.wikipedia.org/wiki/Great-circle_distance#From_chord_length以获得所需的结果。


以下是一些基准。使用N = 100, using_kdtree比 快 39 倍orig(蛮力)方法。

In [180]: %timeit using_kdtree(data)
100 loops, best of 3: 18.6 ms per loop

In [181]: %timeit using_sklearn(data)
1 loop, best of 3: 214 ms per loop

In [179]: %timeit orig(data)
1 loop, best of 3: 728 ms per loop

For N = 10000:

In [5]: %timeit using_kdtree(data)
1 loop, best of 3: 2.78 s per loop

In [6]: %timeit using_sklearn(data)
1 loop, best of 3: 1min 15s per loop

In [7]: %timeit orig(data)
# untested; too slow

Since using_kdtree is O(N log(N)) and orig is O(N**2),因数为 哪个using_kdtreeorig将成长为N,长度data, grows.


import numpy as np
import scipy.spatial as spatial
import pandas as pd
import sklearn.neighbors as neighbors
from math import radians, cos, sin, asin, sqrt

R = 6367

def using_kdtree(data):
    "Based on https://stackoverflow.com/q/43020919/190597"
    def dist_to_arclength(chord_length):
        """
        https://en.wikipedia.org/wiki/Great-circle_distance
        Convert Euclidean chord length to great circle arc length
        """
        central_angle = 2*np.arcsin(chord_length/(2.0*R)) 
        arclength = R*central_angle
        return arclength

    phi = np.deg2rad(data['Latitude'])
    theta = np.deg2rad(data['Longitude'])
    data['x'] = R * np.cos(phi) * np.cos(theta)
    data['y'] = R * np.cos(phi) * np.sin(theta)
    data['z'] = R * np.sin(phi)
    tree = spatial.KDTree(data[['x', 'y','z']])
    distance, index = tree.query(data[['x', 'y','z']], k=2)
    return dist_to_arclength(distance[:, 1])

def orig(data):
    def distance(lon1, lat1, lon2, lat2):
        """
        Calculate the great circle distance between two points 
        on the earth (specified in decimal degrees)
        """
        # convert decimal degrees to radians 
        lon1, lat1, lon2, lat2 = map(radians, [lon1, lat1, lon2, lat2])
        # haversine formula 
        dlon = lon2 - lon1 
        dlat = lat2 - lat1 
        a = sin(dlat/2.0)**2 + cos(lat1) * cos(lat2) * sin(dlon/2.0)**2
        c = 2 * asin(sqrt(a)) 
        km = R * c
        return km

    shortest_distance = []
    for i in range(len(data)):
        distance1 = []
        for j in range(len(data)):
            if i == j: continue
            distance1.append(distance(data['Longitude'][i], data['Latitude'][i], 
                                      data['Longitude'][j], data['Latitude'][j]))
        shortest_distance.append(min(distance1))
    return shortest_distance


def using_sklearn(data):
    """
    Based on https://stackoverflow.com/a/45127250/190597 (Jonas Adler)
    """
    def distance(p1, p2):
        """
        Calculate the great circle distance between two points
        on the earth (specified in decimal degrees)
        """
        lon1, lat1 = p1
        lon2, lat2 = p2
        # convert decimal degrees to radians
        lon1, lat1, lon2, lat2 = map(np.radians, [lon1, lat1, lon2, lat2])
        # haversine formula
        dlon = lon2 - lon1
        dlat = lat2 - lat1
        a = np.sin(dlat/2)**2 + np.cos(lat1) * np.cos(lat2) * np.sin(dlon/2)**2
        c = 2 * np.arcsin(np.sqrt(a))
        km = R * c
        return km
    points = data[['Longitude', 'Latitude']]
    nbrs = neighbors.NearestNeighbors(n_neighbors=2, metric=distance).fit(points)
    distances, indices = nbrs.kneighbors(points)
    result = distances[:, 1]
    return result

np.random.seed(2017)
N = 1000
data = pd.DataFrame({'Latitude':np.random.uniform(-90,90,size=N), 
                     'Longitude':np.random.uniform(0,360,size=N)})

expected = orig(data)
for func in [using_kdtree, using_sklearn]:
    result = func(data)
    assert np.allclose(expected, result)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

查找数据集中所有点距离最近的点 - Python 的相关文章

随机推荐

  • 根据浏览器宽度移动背景图像

    leavesbg background f7fff7 url images leaves4 png repeat y fixed 480px top 因此 如果页面的宽度大于 800 像素 我想将背景图像向右移动一半 也就是说 如果他们以
  • HSV三角形的公式

    不知道下面两个公式是怎么推导出来的 请解释一下 我的声望点太低了 没法去问写公式的人 C 中的 HSV 三角形 https stackoverflow com questions 42531608 hsv triangle in c sha
  • maven-checkstyle-plugin 无法在 macOS 上使用 google_checks.xml

    我有一个 Java Maven 项目 我在家里使用 Windows 构建并正确执行了 checkstyle 它使用内置规则集 但我也尝试了外部文件 查看相同的代码 pom xml 它似乎不适用于 macOS 奇怪的是如果我使用sun che
  • 如何使用 jQuery 选择没有特定类名的元素?

    像我这样的突击队怎么可能使用臭名昭著且功能强大的 jQuery Sizzle CSS 和其他所有东西 选择器来选择一个没有名为 active 的类的元素 我尝试过 a class active etc 但它没有给出足够的结果 a not a
  • OpenCV 中的相机标定和鸟瞰投影

    我已经完成了相机校准 现在我想获得棋盘图片的鸟瞰图 如下所示 但结果很奇怪 看起来不是一个正方形 你可以看到图3 每个正方形都是7 95x7 95 有人知道为什么吗 gpsPoints 0 Point2f gpsPoints 1 Point
  • 从 VS Code 终端 (Windows 10) 打开 VS Code 中的选定文件夹

    我一直在寻找 但在使用 VS Code 终端时找不到任何方法来打开 VS Code 中选定的文件夹 这可能吗 您是否尝试在集成终端所属的同一个 VSCode 实例中打开 Try code r
  • 从新的 Firebase 检索数据

    请帮忙 迁移到新的 Firebase 后 我无法检索数据 使用这个结构 let ref FIRDatabase database reference override func viewDidLoad super viewDidLoad r
  • Spring/Java 错误:命名空间元素“annotation-config”...在 JDK 1.5 及更高版本上

    我有 Spring Java 应用程序 它是用编译器合规级别 1 5 我下载了一个新的 Linux 设置阿帕奇汤姆猫 8 0 8 我下载了JDK 8u5 我在bash中设置的路径如下 PATH PATH HOME jdk1 8 0 05 b
  • 在Android中压缩带有大图像的pdf

    这个问题通过java压缩带有大图像的pdf https stackoverflow com questions 20614350 compress pdf with large images via java给出了在 Java 中使用 iT
  • 您可以同时使用 Protractor 和 Appium 来测试混合应用程序吗?

    这是我的场景 我有一个基于 Angular JS 构建的网站 我能够使用量角器使网站自动化 然而 在网站上执行的某些操作会反映在 Android 和 IOS 设备中 这就是我想要实现的目标 像平常一样在网站上运行我的测试 但我也想触发命令来
  • 如何通过 .NET 将图像插入 Access OLE 字段

    我有一个 Access mdb 数据库 我想从 Visual C 2010 开发的应用程序中插入图像 图片存储在数据库中的 OLE 对象字段中 直接在 Access 中添加图像后 它们将以位图图像的格式存储 双击这些图片即可在 Access
  • Cypress - 验证一列中的每个表行是否包含相同的项目

    我有一个表 但是某种由 DIV 创建的 ag grid 而不是真正的表元素 div div Name 1 div div 25 div div div div Name 1 div div 25 div div 我想验证每个字段是否带有co
  • 有谁知道 CVS 命令行选项来获取上次签入的详细信息?

    我在 Windows 上使用 CVS 带有 WinCVS 前端 并且希望在构建失败时将上次签入的详细信息添加到我们的自动构建过程中的电子邮件中 以便更容易修复 我需要知道已更改的文件 更改它们的用户以及评论 我一直在尝试制定命令行选项 但似
  • 来自 links-own 的参数值

    我需要帮助 所以我想将代理拥有的参数指定为链接拥有的参数值的平均值 frienships own strength household own influence factor to create influence if friendsh
  • 在 Rails 资产管道的 js.coffee 文件中使用 erb 时出错

    我有以下代码 assets javascripts home js coffee erb jQuery gt addClickListeners gt document on click add chord link addChord do
  • C IEEE-Floats inf 等于 inf

    在 C 中 在使用 IEEE 754 浮点数的实现中 当我比较两个 NaN 浮点数时 它返回 0 或 false 但是为什么两个都为 inf 的浮点数会被视为相等呢 该程序打印 equal 至少在带有 gcc 的 Linux AMD64 下
  • 使用 strtotime() 在 php 中计算相对日期

    我正在寻找一种可靠的方法来返回指定工作日 例如 星期一 的完整日期current week 由于今天是 2012 年 6 月 13 日星期三 我预计以导致2012 06 11 而是 php 返回2012 06 18好像它解释了本星期作为意义
  • 核心数据:3表连接?

    我知道 Core Data 不是数据库 有很多区别 是这个吗 在数据库中 我通常会有以下内容 A gt gt B gt gt C A 有很多 B B 有很多 C 查询 给我所有具有 c attr X 的 A 很容易写成 select fro
  • 关于 string.c_str() 生命周期

    我想知道是否void func const char str 参考有效的str如果我写如下 auto str string hello c str func str 它与下面的代码有何不同 func string hello c str 在
  • 查找数据集中所有点距离最近的点 - Python

    我有一个数据集如下 Id Latitude longitude 1 25 42 55 47 2 25 39 55 47 3 24 48 54 38 4 24 51 54 54 我想找到数据集每个点的最近距离 我在互联网上找到了以下距离函数