Spark轨迹大数据高效处理_计算两经纬度点间的距离_使用Haversine formula公式

news2024/11/15 7:56:56

开发背景

        接上文我求的两经纬度点之间的方位角,我的需求里还提到了要计算距离,当然这个距离也是为后面的需求做铺垫的,因此需要求两个经纬度电之间的距离。

        不要妄想用勾股定理求出来,实际上距离的计算还是稍微复杂些。这里使用的是Haversine公式,用于在给定两个地理坐标点的情况下计算它们之间的球面距离,我直接将这个公式的数学计算实现为一个方法,然后再代码中调用。

生产环境使用(球面短距离计算)

        Haversine公式的数学理论基于球面三角学和三角恒等式的推导,通过近似计算大圆航线距离,适用于小距离的球面距离计算。这基本符合我的需求,因为我的计算都是基本是短距离计算的,基本不会跨省,实际效果也不错,如果你是超远距离计算,比如跨国,跨洲了,可以先试试,然后再考虑使用。

                        来源 https://wikipredia.net/zh/Haversine_formula#Formulation

说完理论部分,我就要开始上代码了,基本上你配置完spark环境,直接把我的代码扔上去就能看到输出结果,因为我是做了很多遍验证的。

spark代码

这个你可以转成python,反正算法基本都一样,不过换了一种写法

import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._


/**
 * 增加了多对多的方位角计算以及计算对应距离模型计算方法
 * 代码实现了计算多个点位对多个点位的方位角计算以及对应的距离计算,基本算是final版本
 * 基本实现了角度计算和距离计算
 * 在实际生产中,会出现噪音点,以及点位null值等,还是提前清洗一下数据为好
 * 2024年8月6日写,几个月前就搞好了,一直没空发博客。。。今天又闲下来了,干就完了,有问题及时联系
 * @email matrix70@163.com
 * @author lixh
 */
object Angle_MoreToMore_Distance {
  /**
   * @author lixh
   * @param lon1
   * @param lat1
   * @param lon2
   * @param lat2
   * @return
   */
  // 计算两个经纬度坐标之间的方位角
  def calculateAzimuth(lon1: Double, lat1: Double, lon2: Double, lat2: Double): Double = {
    val dx = lon2 - lon1
    val dy = lat2 - lat1
    val azimuth = math.atan2(dx, dy) * 180 / math.Pi
    (azimuth + 360) % 360
  }
  //距离算法 Haversine @author lixh
  def haversineDistance(lat1: Double, lon1: Double, lat2: Double, lon2: Double): Double = {
    val toRadians = Math.toRadians(_: Double)
    val dLat = toRadians(lat2 - lat1)
    val dLon = toRadians(lon2 - lon1)
    val a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
      Math.cos(toRadians(lat1)) * Math.cos(toRadians(lat2)) *
        Math.sin(dLon / 2) * Math.sin(dLon / 2)
    val c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))
    val EARTH_RADIUS_KM = 6371.0
    val distance = EARTH_RADIUS_KM * c
    distance
  }

  def main(args: Array[String]): Unit = {
    val spark = SparkSession.builder()
      .appName("Azimuth Calculation") // 设置应用程序名称
      .master("local[*]") // 运行模式,这里使用本地模式
      .getOrCreate()

    import spark.implicits._

    // DF A 包含地点信息和经纬度信息 @author https://blog.csdn.net/qq_52128187?type=blog    val A = Seq((101, "北京", 39.9042, 116.4074),
      (102, "广州", 23.16, 113.23)
    ).toDF("id1", "name1", "latitudeA", "longitudeA")

    // DF C 包含地点信息和经纬度信息
    val C = Seq(
      (101, "吉林", 43.8171, 125.3235),
      (101, "黑龙江", 45.8023, 126.5350),
      (102, "江苏", 32.0603, 118.7969),
      (102, "浙江", 30.2875, 120.1536),
      (101,"新疆", 43.77, 87.68),
      (102, "台湾省", 25.05, 121.50)
    ).toDF("id2", "name2", "latitudeC", "longitudeC")

    val calculateAzimuthUDF = udf(calculateAzimuth _)

    // 执行内连接操作,计算方位角并添加到新列 "azimuth"
    val azimuthDF = A.join(C, A("id1") === C("id2"))
      .withColumn("azimuth", calculateAzimuthUDF($"longitudeA", $"latitudeA", $"longitudeC", $"latitudeC"))

    // 计算得到的方位角数据
    azimuthDF.show(false)
    val haversineDistanceUDF = udf((lat1: Double, lon1: Double, lat2: Double, lon2: Double) => haversineDistance(lat1, lon1, lat2, lon2))

    //距离字段添加,@author lixh
    val resultDf = azimuthDF.withColumn("distance", haversineDistanceUDF($"latitudeA", $"longitudeA", $"latitudeC", $"longitudeC"))
    resultDf.show()

    spark.stop()
  }
}

代码输出结果

到这里基本就完成了,你可以对输出结果进行小数点位限制,一个round函数就解决。

参考资料:

https://wikipredia.net/zh/Haversine_formula

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于Libarary loader转化成16.6的使用方法

关于Libarary loader转化成16.6的使用方法 直接去贸泽下载程序,免费使用的 2.开始安装 出现图标 3.桌面新建文件夹作为文件生成路径 4.下载ECAD模型的文件 5.打开Library loader 6.这玩意需要搞个邮箱注册,可以用QQ邮箱随便注册一个 7.将下载的文件放…

VBA 指定快捷键在Excel中粘贴指定缩放图片

1. 应用背景 做测试的时候需要在Excel文件中贴图,但是直接粘贴的话图片又太大,需要手动调整,这时就可以利用这个宏来实现一次性粘贴并调整好图片的大小。 2. 宏的制作 可以是.xlsm文件,将该文件放到[C:\Program Files\Microsof…

YOLO:使用labelme进行图片数据标签制作,并转换为YOLO格式

作者:CSDN _养乐多_ 本文将介绍如何使用 labelme 进行图片数据标签制作的方法,并将标签的格式从 JSON 格式转换为 YOLO 格式。 文章目录 一、安装labelme二、使用流程三、json格式转为YOLO格式四、按比例划分数据集(训练、验证、测试&#…

Black Hat USA 2024:微软AI助手Copilot安全隐患曝光

在Black Hat USA 2024,一位研究人员披露了微软AI助手Copilot存在的多个安全隐患,攻击者能够借此漏洞窃取敏感数据和企业凭证。 微软声称,通过将任务委派给AI助手Copilot,每天可以节省数百小时的工作时间。Copilot是微软在2023年2月…

MindSearch:用于增强网络搜索效率的开源人工智能

Web 信息查找与集成是搜索、检索、提取或集成 Web 资源以满足特定需求的活动,是实际生活中几乎所有领域中每个决策和解决问题的实体都必须执行的操作。 大型语言模型 (LLM) 与搜索引擎的集成重新定义了我们在网络上查找和使用信息的方式。因此,LLM 能够…

开放式耳机好用吗?开放式耳机推荐

开放式耳机好用吗? 开放式耳机确实在特定场景下表现出色,它们有着独特的优点,使得不少用户对其青睐有加。 首先,从舒适度来看,开放式耳机避免了入耳式耳机可能带来的耳道压迫感,长时间佩戴也能保持相对舒适…

开源力量,智领云KDP为大数据处理领域注入云原生活力

在数字化转型的浪潮中,大数据处理已成为企业挖掘价值、驱动决策的核心引擎。随着云原生技术的兴起,如何高效、灵活地管理和分析海量数据成为行业面临的新挑战。在此背景下,开源技术以其强大的社区支持、灵活性和可扩展性,正逐步成…

深入理解Java设计模式:23种模式的全面解析

深入理解Java设计模式:23种模式的全面解析 一、创建型模式1. 单例(Singleton)模式2. 原型(Prototype)模式3. 工厂方法(Factory Method)模式4. 抽象工厂(Abstract Factory&#xff09…

JavaWeb中的Servlet

本笔记基于【尚硅谷全新JavaWeb教程,企业主流javaweb技术栈】https://www.bilibili.com/video/BV1UN411x7xe?vd_sourcea91dafe0f846ad7bd19625e392cf76d8总结 Servlet Servlet简介 动态资源和静态资源 静态资源 无需在程序运行时通过代码运行生成的资源,在程序运…

Chapter 30 多态

欢迎大家订阅【Python从入门到精通】专栏,一起探索Python的无限可能! 文章目录 前言一、基本概念二、抽象类 前言 多态(Polymorphism)是面向对象编程中的核心概念,本章将详细讲解 Python 中多态的实现方式以及如何应用…

SQL Zoo 8.Using Null

以下数据均来自SQL Zoo 1.List the teachers who have NULL for their department.(列出所属部门为NULL的教师) select name from teacher where dept is null 2.Note the INNER JOIN misses the teachers with no department and the departments wit…

【Git】Git安装_配置

一、Git的安装 1. 下载Git 官方下载:访问Git的官方网站https://git-scm.com/,在首页找到下载链接。但需要注意的是,由于Git的服务器位于国外,直接下载可能会比较慢。镜像下载:推荐使用国内的镜像网站进行下载&#x…

【Canvas与艺术】蓝波纹白底黄星徽章

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>蓝波纹白底黄星徽章</title><style type"text/css&qu…

《系统架构设计师教程(第2版)》第13章-层次式架构设计理论与实践-04-数据访问层设计

文章目录 1. 五种数据访问模式1.1 在线访问1.2 DAO1.3 DTO1.4 离线数据模式1.5 对象/关系映射 (O/R Mapping) 2. 工厂方法模式在数据访问层应用3 ORM、Hibernate与CMP2.0设计思想3.1 ORM3.2 Hibernate1&#xff09;概述2&#xff09; Hibernate的架构&#xff08;2023年的考题&…

SpringBoot统一功能处理——统一数据返回格式

目录 一、简单使用 二、存在的问题描述 三、优点 一、简单使用 统一的数据返回格式使用 ControllerAdvice 和 ResponseBodyAdvice 的方式实现 ControllerAdvice 表示控制器通知类。 添加类 ResponseAdvice , 实现 ResponseBodyAdvice 接口&#xff0c;并在类上添加 …

【jQuery】入门学习篇

文章目录 一、前言&#x1f680;&#x1f680;&#x1f680;二、jQuery简介及使用详解&#xff1a;☀️☀️☀️2.1 jQuery简介2.2 引入jQuery① 第一种引入方式&#xff1a;直接路径引入② 第二种引入方式&#xff1a;使用第三方CDN 后序还在更新中~~~三、总结&#xff1a;&am…

C++_基本语法笔记_类和对象

对于有Java基础的思想不过多记录&#xff0c;仅看语法 创建和封装对象 类似Java中的set操作&#xff0c;可以写一个赋值操作用于给实例化对象赋属性值 三种权限&#xff1a;public &#xff0c; protect &#xff0c;private Class和Struct区别 Struct默认为public权限cla…

SpringBoot统一功能处理——拦截器

目录 一、什么是拦截器&#xff1f; 二、拦截器使用 2.1 定义拦截器 2.2 注册配置拦截器 三、拦截器详解 3.1 拦截器的拦截路径配置 3.2 拦截器执行流程 一、什么是拦截器&#xff1f; 拦截器是Spring框架提供的核心功能之一, 主要用来拦截用户的请求, 在指定方法前后,…

C语言 | Leetcode C语言题解之第332题重新安排行程

题目&#xff1a; 题解&#xff1a; char* id2str[26 * 26 * 26];int str2id(char* a) {int ret 0;for (int i 0; i < 3; i) {ret ret * 26 a[i] - A;}return ret; }int cmp(const void* _a, const void* _b) {int **a (int**)_a, **b (int**)_b;return (*b)[0] - (*…

python网络爬虫使用代理

Python网络爬虫使用代理的实用指南 在网络爬虫的开发过程中&#xff0c;使用代理是一个非常重要的环节。代理不仅可以帮助爬虫绕过反爬虫机制&#xff0c;还能保护开发者的隐私。本文将介绍如何在Python中使用代理进行网络爬虫&#xff0c;包括基本的设置和示例代码。 1. 代理…