Spark实现在一定时间范围内 求用户在所有基站(lac)停留的时长 再取top2

本文介绍了一个使用Apache Spark处理大规模移动用户数据的应用案例。通过读取用户在不同基站的活动记录,计算每个用户在各基站的总停留时间,并结合基站的经纬度信息,最终找出每个用户停留时间最长的两个基站及其位置。这一过程涉及数据清洗、聚合、Join操作及排序等关键步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.qf.gp1707.day06

import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * 需求:在一定时间范围内  求用户在所有基站(lac)停留的时长  再取top2
  * 1.用户分别在所有基站停留的各个总时长
  * 2.把经纬度信息join过来
  * 3.按照手机号进行分组
  * 4.组内排序,并取top2
  */
object MobileLocation {
  def main(args: Array[String]): Unit = {
    val conf=new SparkConf()
      .setAppName("mobilelocation")
      .setMaster("local[2]")
    val sc=new SparkContext(conf)

    //获取用户基站信息
    val files:RDD[String]=sc.textFile("./src/main/scala/com/qf/gp1707/day06/lacduration/log")

    val phoneAndLacAndTime:RDD[((String,String),Long)]=files.map(line=>{
      val fields:Array[String]=line.split(",")//切分每一行数据
      val phone=fields(0)//用户手机号
      val time=fields(1).toLong//时间戳
      val lac=fields(2)//基站
      val eventType=fields(3)//事件类型
      val time_long=if(eventType==1) -time else time
      ((phone,lac),time_long)
    })

//    用户在相同的基站停留的时长
    val sumedPhoneAndLacAndTime:RDD[((String,String),Long)]=phoneAndLacAndTime.reduceByKey(_+_)

    //为了便于和经纬度进行join,需要把lac放到key的位置
    val lacAndPhoneAndTime:RDD[(String,(String,Long))]=sumedPhoneAndLacAndTime.map(line=>{
      val phone=line._1._1//手机号
      val lac=line._1._2//基站ID
      val time=line._2//用户在该基站停留的总时长
      (lac,(phone,time))
    })

    //    获取基站的基础信息
    val lacInfo: RDD[String] = sc.textFile("./src/main/scala/com/qf/gp1707/day06/lacduration/lac_info.txt")

    val lacAndXY: RDD[(String, (String, String))] = lacInfo.map(line => {
      val fields = line.split(",")
      val lac = fields(0) //基站ID
      val x = fields(1)//经度
      val y = fields(2)//纬度
      (lac, (x, y))
    })
    //把经纬度信息join到用户访问信息
    val joined: RDD[(String, ((String, Long), (String, String)))] =
      lacAndPhoneAndTime.join(lacAndXY)

    val phoneAndTimeAndXY: RDD[(String, Long, (String, String))] =
      joined.map(x => {
      val phone = x._2._1._1
        //手机号
      val lac = x._1
      //基站ID
      val time = x._2._1._2
      //停留时长
      val xy = x._2._2 //经纬度

      (phone, time, xy)
    })

    //按照用户手机号进行分组
    val grouped: RDD[(String, Iterable[(String, Long, (String, String))])]
    = phoneAndTimeAndXY.groupBy(_._1)

    //按照时长进行降序排序
    val sorted: RDD[(String, List[(String, Long, (String, String))])]
    = grouped.mapValues(_.toList.sortBy(_._2).reverse)

    //取top2

    val top2: RDD[(String, List[(String, Long, (String, String))])] = sorted.mapValues(_.take(2))

    println(top2.collect().toBuffer)

  }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值