轨迹大数据分析:革命性的地理空间分析与Apache Spark:处理空间不连续的点数据


import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
//2023年12月22日
// bylee
//邮箱:matrix70@163.com
object 跨本初子午线_添加点v1 {
  def main(args: Array[String]): Unit = {

    //创建样例数据集,包含id、lon、lat和time四列
    // 计算每个id下相邻两个点的lon差值,
    // 如果差值大于180度,则记录该位置。接着在这些位置插入新的数据行,将lon设置为180,将lat设置为相邻两点lat的平均值,
    // 将time设置为相邻两点时间的平均值。最后将原始数据和新添加的数据合并,并按id和time排序展示。

    // 创建SparkSession
    val spark = SparkSession.builder.appName("PointDataProcessing").getOrCreate()

    // 创建样例数据
    val data = Seq(
      (1, 100.0, 50.0, "2022-01-01 12:00:00"),
      (1, -100.0, 55.0, "2022-01-01 12:30:00"),
      (2, 80.0, 40.0, "2022-01-01 13:00:00"),
      (2, 100.0, 45.0, "2022-01-01 14:00:00"),
      (3, 170.0, 60.0, "2022-01-01 15:00:00"),
      (3, -170.0, 65.0, "2022-01-01 16:00:00")
    )

    // 将数据转换为DataFrame
    val df = data.toDF("id", "lon", "lat", "time")

    // 注册DataFrame为临时表
    df.createOrReplaceTempView("point_data")

    // 定义处理函数
    def processPointData(inputDf: DataFrame): DataFrame = {
      import spark.implicits._

      // 计算连续两个点的lon差值
      val lonDiffColumn = lag($"lon", 1).over(Window.partitionBy("id").orderBy("time")).as("prev_lon")
      val dfWithLonDiff = inputDf.withColumn("lon_diff", when(abs($"lon" - $"prev_lon") > 180, true).otherwise(false))

      // 添加新数据行
      val interpolatedData = dfWithLonDiff.filter($"lon_diff" === true)
        .withColumn("lon", lit(180)) // 新lon值设为180
        .withColumn("lat", (lag($"lat", 1).over(Window.partitionBy("id").orderBy("time")) + $"lat") / 2) // 新lat值为相邻两点的平均值
        .withColumn("time", (unix_timestamp($"time") + unix_timestamp(lag($"time", 1).over(Window.partitionBy("id").orderBy("time")))) / 2) // 新time值为相邻两点时间的平均值

      // 合并原始数据和新添加的数据
      val resultDf = inputDf.union(interpolatedData).orderBy("id", "time")

      return resultDf
    }

    // 调用处理函数并显示处理结果
    val processedDf = processPointData(df)
    processedDf.show()


    //v2版本:使用DataFrame API的join操作来实现相同的逻辑。这种方法避免了使用窗口函数,因此在数据量较大时可能具有更好的性能
    // 定义处理函数
/*    def processPointDataWithJoin(inputDf: DataFrame): DataFrame = {
      import spark.implicits._

      // 计算连续两个点的lon差值
      val dfWithLeadLon = inputDf.withColumn("lead_lon", lead($"lon", 1).over(Window.partitionBy("id").orderBy("time")))
      val dfWithLonDiff = dfWithLeadLon.withColumn("lon_diff", when(abs($"lead_lon" - $"lon") > 180, true).otherwise(false))

      // 添加新数据行
      val interpolatedData = dfWithLonDiff.filter($"lon_diff" === true)
        .withColumn("lon", lit(180)) // 新lon值设为180
        .withColumn("lat", (lead($"lat", 1).over(Window.partitionBy("id").orderBy("time")) + $"lat") / 2) // 新lat值为相邻两点的平均值
        .withColumn("time", (unix_timestamp($"time") + unix_timestamp(lead($"time", 1).over(Window.partitionBy("id").orderBy("time")))) / 2) // 新time值为相邻两点时间的平均值

      // 合并原始数据和新添加的数据
      val resultDf = inputDf.join(interpolatedData, Seq("id", "lon", "lat", "time"), "outer").orderBy("id", "time")

      return resultDf
    }

    // 调用使用join的处理函数并显示处理结果
    val processedDfUsingJoin = processPointDataWithJoin(df)
    processedDfUsingJoin.show()*/




  }
}

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值