KDTree空间搜索算法学习

目录

  • KDTree(K-Dimensional Tree)原理
  • 步骤
    • 空间索引建立例子[^1]
    • 回溯搜索例子[^2]
  • 相关包
  • 案例[^3]
    • 数据
    • KDTree 识别轨道衔接出行
    • 轨道衔接单车骑行范围分析
    • 结果保存

KDTree(K-Dimensional Tree)原理

将需要匹配的 K 维空间点建立 K 维树空间索引,在近邻匹配时,输入的点在树中快速检索,即可找到最近邻的点。
在建立空间索引二维树时,算法复杂度介于 O ( l o g 2 n ) O(log_2n) O(log2n) O ( n ) O(n) O(n)之间。

  • 最好的情况下,每次插入点能均匀分割剩余点,算法复杂度为 O ( l o g 2 n ) O(log_2n) O(log2n)
  • 最坏的情况下,每次插入点其余点都在一个字空间中,树的深度为n,算法复杂度为 O ( n ) O(n) O(n)

步骤

  1. 空间索引建立
    • 给定或选择中心节点
    • 依次从各维度分割
    • 按照层次插入点,建立空间索引
      KDTree索引
  2. 最近邻搜索
    • 给定数据点,查询与其距离最近的点
    • 从根节点开始依次向下搜索,进行深度优先遍历(二分搜索),直到与待查询点处于同一子空间的叶子结点
    • 回溯搜索路径、判断路径上其它子节点空间中,是否可能有距离更近的点
      • 如过有可能,跳转到其他子空间去搜索,将其他子节点加入搜索路径
      • 待查询点为圆心,以待查询点到叶子结点的距离为半径作圆,如果不相交则不必去其他字空间搜索
    • 重复过程,直到搜索路径为空
      KDTree搜索

空间索引建立例子1

  • 二维样例:{(2,3),(5,4),(9,6),(4,7),(8,1),(7,2)}
  • 根据x轴中位数,选择中心点为(7,2)
  • 首先在 x 轴维度上,比较其余点和中心点的大小,划分双支
    • 左支:{(2,3),(5,4),(4,7)}
    • 右支:{(9,6),(8,1)}
  • 更新分割轴y轴
  • 确定子节点
    • 左节点
      • 在左支中找到y轴的中位数(5,4)
      • 左支数据更新为{(2,3)},右支数据更新为{(4,7)}
    • 右节点
      • 在右支中找到y轴的中位数(9,6)
      • 左支数据更新为{(8,1)},右支数据为null。
  • 更新分割轴x轴
    • 确定(5,4)的子节点
      • 左节点:由于只有一个数据,所以,左节点为(2,3)
      • 右节点:由于只有一个数据,所以,右节点为(4,7)
    • 确定(9,6)的子节点

回溯搜索例子2

回溯搜索

相关包

sklearn、SciPy、TransBigData、BioPython 中都提供了 KDTree 相关算法接口

  • class sklearn.neighbors.KDTree(X, leaf_size=40, metric=‘minkowski’, **kwargs)
    sklearn.neighbors.KDTree

  • class scipy.spatial.KDTree(data, leafsize=10, compact_nodes=True, copy_data=False, balanced_tree=True, boxsize=None)
    scipy.spatial.KDTree

  • transbigdata.ckdnearest(dfA_origin, dfB_origin, Aname=[‘lon’, ‘lat’], Bname=[‘lon’, ‘lat’])

  • classBio.KDTree.KDTree.KDTree(dim, bucket_size=1)

案例3

数据

共享单车数据

BIKE_IDDATA_TIMELOCK_STATUSLONGITUDELATITUDE
单车ID数据采集时间单车开关锁状态GPS经度GPS维度

共享单车数据

metro_station.csv地铁站数据

KDTree 识别轨道衔接出行

#定义函数,用cKDTree匹配点与点,点与线
import numpy as np
from scipy.spatial import cKDTree
import itertools
from operator import itemgetter
#定义KDTree的函数
def ckdnearest(dfA_origin,dfB_origin,Aname = ['slon','slat'],Bname = ['lon','lat']):gdA = dfA_origin.copy()gdB = dfB_origin.copy()from scipy.spatial import cKDTree#为gdB表的点建立KDTreebtree = cKDTree(gdB[Bname].values)#在gdB的KDTree中查询gdA的点,dist为距离,idx为gdB中离gdA最近的坐标点dist,idx = btree.query(gdA[Aname].values,k = 1)#构建匹配的结果gdA['dist'] = distgdA['index'] = idxgdB['index'] = range(len(gdB))gdf = pd.merge(gdA,gdB,on = 'index')#计算import CoordinatesConvertergdf['dist'] = CoordinatesConverter.getdistance(gdf[Aname[0]],gdf[Aname[1]],gdf[Bname[0]],gdf[Bname[1]])return gdf#读取轨道站点数据
metro_station = pd.read_csv(r'data/metro_station.csv')
metro_station = metro_station.drop_duplicates(subset= 'stationnames')
metro_station = metro_station[['stationnames','lon','lat']]#匹配起点最近的地铁站
metro_station.columns = ['o_station','o_lon','o_lat']
data_move_metro = ckdnearest(data_move_cleaned,metro_station,Aname = ['slon','slat'],Bname = ['o_lon','o_lat'])
data_move_metro = data_move_metro.rename(columns = {'dist':'o_dist'})#匹配终点最近的地铁站
metro_station.columns = ['d_station','d_lon','d_lat']
data_move_metro = ckdnearest(data_move_metro,metro_station,Aname = ['elon','elat'],Bname = ['d_lon','d_lat'])
data_move_metro = data_move_metro.rename(columns = {'dist':'d_dist'})
data_move_metro.iloc[:2].T    #筛选距离地铁站100米范围内的出行数据
data_move_metro = data_move_metro[(data_move_metro['o_dist']<100)|(data_move_metro['d_dist']<100)]
data_move_metro.iloc[:2].T

轨道衔接单车骑行范围分析

#选取某站点
station = '同济大学'
#提取地铁站衔接出行的另一端点分布
tmp1 = data_move_metro[(data_move_metro['o_station']==station)&(data_move_metro['o_dist']<=100)][['elon','elat']]
tmp2 = data_move_metro[(data_move_metro['d_station']==station)&(data_move_metro['d_dist']<=100)][['slon','slat']]
tmp1.columns = ['lon','lat']
tmp2.columns = ['lon','lat']
points = pd.concat([tmp1,tmp2])#转换为GeoDataFrame
points = geopandas.GeoDataFrame(points)
points['geometry'] = geopandas.points_from_xy(points['lon'],points['lat'])points.plot()

站点骑行衔接需求点分布

#读取轨道站点数据
metro_station = pd.read_csv(r'data/metro_station.csv')
metro_station = metro_station.drop_duplicates(subset= 'stationnames')
#提取这个站点的记录
thisstop = metro_station[metro_station['stationnames']==station]
thisstop = geopandas.GeoDataFrame(thisstop)
thisstop['geometry'] = geopandas.points_from_xy(thisstop['lon'],thisstop['lat'])
thisstop
stationnameslinenamelonlatgeometry
同济大学地铁10号线(新江湾城-虹桥火车站)121.50206731.284578POINT (121.50207 31.28458)
#取得这个站点的位置
lon_thisstop = thisstop['lon'].iloc[0]
lat_thisstop = thisstop['lat'].iloc[0]
#确定显示范围
bounds = [lon_thisstop-0.03,lat_thisstop-0.03,lon_thisstop+0.03,lat_thisstop+0.03]import matplotlib.pyplot as plt
fig = plt.figure(1,(6,5),dpi = 300)
ax = plt.subplot(111)
plt.sca(ax)
#加载底图
import transbigdata as tbd
#绘制底图
tbd.plot_map(plt,bounds,zoom = 14,style = 4)
points.plot(ax = ax,markersize = 1)
#标注地铁站点
thisstop.plot(ax = ax,c = 'red',markersize = 8,zorder = 2,label = station+'地铁站')
plt.legend()
#设置显示范围
plt.axis('off')
ax.set_xlim(bounds[0],bounds[2])
ax.set_ylim(bounds[1],bounds[3])
plt.show()

共享单车衔接需求分布

#剔除距离过远的点,否则核密度估计可能会出错
points = points[(points['lon']>bounds[0])&
(points['lat']>bounds[1])&
(points['lon']<bounds[2])&
(points['lat']<bounds[3])]import matplotlib.pyplot as plt
fig = plt.figure(1,(6,5),dpi = 300)
ax = plt.subplot(111)
plt.sca(ax)
#加载底图
import transbigdata as tbd
bounds = [lon_thisstop-0.05,lat_thisstop-0.05,lon_thisstop+0.05,lat_thisstop+0.05]
#绘制底图
tbd.plot_map(plt,bounds,zoom = 13,style = 4)
#标注地铁站点
thisstop.plot(ax = ax,c = 'blue',markersize = 8,zorder = 2,label = station+'地铁站')
plt.legend()
#设置显示范围
plt.axis('off')
ax.set_xlim(bounds[0],bounds[2])
ax.set_ylim(bounds[1],bounds[3])
plt.title(station+'地铁站共享单车衔接范围')
#设置色标
import matplotlib
cmapname = 'autumn_r'
cmap = matplotlib.cm.get_cmap(cmapname)
cax = plt.axes([0.08, 0.4, 0.02, 0.3])
#色标的标题
plt.title('核密度')
import seaborn as sns
#绘制二维核密度图
sns.kdeplot(points['lon'],points['lat'],#指定x与y坐标所在的列data = points,alpha = 0.8,#透明度gridsize = 180, #绘图精细度,越高越慢bw = 0.1,    #高斯核大小(经纬度),越小越精细cmap = cmap, #定义colormapax = ax, #指定绘图位置shade=True, #等高线间是否填充颜色shade_lowest=False,#最底层不显示颜色cbar=True, #显示colorbarcbar_ax=cax,#指定colorbar位置zorder = 1 #控制绘图顺序,使其不会挡住地铁站点)
plt.show()

共享单车核密度可视化

结果保存

points[['lon','lat']].to_csv(r'data/bicycle_connection_points.csv',index = None)

bicycle_connection_points.csvbicycle_connection_points


  1. KD-Tree原理详解 ↩︎

  2. KD-Tree详解: 从原理到编程实现 ↩︎

  3. 《交通时空大数据分析、挖掘与可视化(Python版)》 ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/321274.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git中单独的功能特性分支是什么含义

在Git中&#xff0c;一个"功能特性分支"&#xff08;通常简称为“特性分支”&#xff09;是指从主开发分支&#xff08;比如main或master&#xff09;独立出来的分支&#xff0c;专门用于开发一个新功能、修复一个bug&#xff0c;或者进行实验性的尝试。使用特性分支…

开源的聊天服务器tigase 7.1.3 相关文档

官方的api文档 7.1.3&#xff1a; Tigase Administration Guide github地址&#xff1a; Release 7.1.3 tigase/tigase-server GitHub 安装教程&#xff1a; Tigase手动安装过程-腾讯云开发者社区-腾讯云

Pascal Content数据集

如果您想使用Pascal Context数据集&#xff0c;请安装Detail&#xff0c;然后运行以下命令将注释转换为正确的格式。 1.安装Detail 进入项目终端 #即 这是在我自己的项目下直接进行克隆操作&#xff1a; git clone https://github.com/zhanghang1989/detail-api.git $PASCAL…

标准IO函数-将bmp图片修改为德国国旗样式

代码&#xff1a; #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <pthread.h> #include <semaphore.h…

C#修改默认参数settings文件

右击项目在设置中进行修改&#xff1a; 千万不要在这里改。 如果要在自己的项目里添加这个文件&#xff0c;首先新建个文件夹&#xff0c;然后添加.setting文件&#xff0c;然后再像上面说的那样添加属性。

unity华为sdk接入指路指南

目前比较靠谱的几个方案&#xff1a;试过几个仅供参考 温馨提示&#xff1a;最高目前可支持方案到unity2021版本以下&#xff0c;以上请联系华为官方寻求技术支持 Unity集成华为游戏服务SDK方式&#xff08;一&#xff09;&#xff1a;集成Unity官方游戏SDK&#xff1a; 华为…

Quora 首席执行官亚当·德安杰洛 (Adam D’Angelo) 谈论了 AI、聊天机器人平台 Poe,以及 OpenAI 为什么不是竞争对手

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

精酿啤酒:种类与风格的多样性探索

啤酒&#xff0c;这一古老的酒精饮品&#xff0c;随着时代的发展与技术的进步&#xff0c;已经衍生出了无数种类与风格。其中&#xff0c;精酿啤酒在近年来备受瞩目&#xff0c;以其与众不同的酿造工艺和风味&#xff0c;成为了啤酒爱好者们的新宠。Fendi club 啤酒&#xff0c…

【PCIE】基于PCIE4C的数据传输(四)——使用MSIX中断

基于PCIE4C的数据传输&#xff08;三&#xff09;——遗留中断与MSI中断 一文介绍了遗留中断与MSI中断两种中断方式的代码实现&#xff0c;本文继续基于Xilinx UltrascaleHBM VCU128开发板与linux&#xff08;RHEL8.9&#xff09;&#xff0c;介绍MSIX中断方式的代码实现。本文…

ROS机器人实用技术与常见问题解决

问题速查手册&#xff08;时实更新&#xff09;更加全面丰富的问题手册记录 1.机器人使用GPARTED挂载未分配空间 需要在图型界面下操作&#xff0c;建议使用no machine连接 安装gparted磁盘分区工具, sudo apt-get install gparted -y 启动软件 sudo gparted 点击磁盘/内存…

ILI9341显示驱动芯片的使用

ILI9341是一种常见的TFT LCD显示驱动芯片&#xff0c;它在众多的应用中都有广泛的使用。这种芯片的一个显著特点是它支持16位RGB565颜色&#xff0c;这意味着它可以显示多达65536种不同的颜色。这使得ILI9341能够提供鲜艳、生动的色彩效果&#xff0c;对于需要表现丰富色彩的应…

外网禅道配置

exportfs -avrf 修改代码&#xff0c;避免启动太慢&#xff1a;vi /opt/zbox/bin/zbox.php 启动和停止 /opt/zbox/zbox start /opt/zbox/zbox stop

【MATLAB源码-第204期】基于matlab的语音降噪算法对比仿真,谱减法、维纳滤波法、自适应滤波法;参数可调。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 语音降噪技术的目的是改善语音信号的质量&#xff0c;通过减少或消除背景噪声&#xff0c;使得语音更清晰&#xff0c;便于听者理解或进一步的语音处理任务&#xff0c;如语音识别和语音通讯。在许多实际应用中&#xff0c;如…

保研面试408复习 1——操作系统、计网、计组

文章目录 1、操作系统一、操作系统的特点和功能二、中断和系统调用的区别 2、计算机组成原理一、冯诺依曼的三个要点二、MIPS&#xff08;每秒百万条指令&#xff09;三、CPU执行时间和CPI 3、计算机网络一、各个层常用协议二、网络协议实验——数据链路层a.网络速率表示b.数据…

Linux中的YUM源仓库和NFS文件共享服务

目录 1.YUM仓库服务 1.1 YUM概述 1.2 准备安装源 1.3 搭建yum本地ftp源仓库 1.4 yum在线源替换方法 1.5 yum的常用操作命令 2.NFS文件共享服务 2.1 NFS&#xff08;共享存储服务&#xff09;简介 2.2 NFS服务的实现 2.3 使用NFS发布共享资源 2.4 NSF配置 2.5 如何指…

matlab

图像配准&#xff1a; %手动选择执行图片(由于程序为分开&#xff0c;此处保存的mat文件为图MRI6的信息&#xff0c;所以请选择图MRI6) [filename,pathname]uigetfile({*.jpg;*.bmp;*.tif;*.png;*.gif,All Image Files;*.*,All Files}); image imread([pathname,filename]); …

LNMP一键安装包

LNMP一键安装包是什么? LNMP一键安装包是一个用Linux Shell编写的可以为CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian/Deepin/Alibaba/Amazon/Mint/Oracle/Rocky/Alma/Kali/UOS/银河麒麟/openEuler/Anolis OS Linux VPS或独立主机安装LNMP(Nginx/MySQL/PHP)、LNMPA(Nginx/MySQ…

基于vue.js+thymeleaf模板引擎+ajax的注册登陆简洁模板(含从零到一详细介绍)

文章目录 前言1、数据库准备2、工具类与相关基类使用2.1、工具类2.2、相关基类 3、web包目录说明4、注册功能设计&#xff08;本文核心部分&#xff09;4.1、注册页面设计4.2、注册逻辑设计 5、登陆功能设计5.1、登陆页面设计5.2、登陆逻辑设计 6、运行效果图 前言 大多数的网…

Finder Windows for Mac:双系统窗口,一键切换!

Finder Windows for Mac是一款专为Mac用户设计的实用工具&#xff0c;它模拟了Windows系统的窗口管理功能&#xff0c;让Mac用户也能享受到类似Windows的窗口操作体验。这款软件的主要功能是提供一个浮动面板&#xff0c;帮助用户随时即时访问打开的Finder窗口列表&#xff0c;…

HCIP的学习(OSPF总篇)

HCIA的复习 这边可以与我之前写的HCIA博客结合起来一起看&#xff0c;效果更好 HCIA的学习&#xff08;6&#xff09; OSPF状态机 down—关闭-----一旦启动OSPF进程&#xff0c;并发出hello报文&#xff0c;则进入下一个状态init----初始化状态------当收到的hello报文中存在…