现有如下数据文件需要处理
格式:CSV
位置:hdfs://myhdfs/input.csv
大小:100GB
字段:用户ID,位置ID,开始时间,停留时长(分钟)

4行样例:

UserA,LocationA,2018-01-01 08:00:00,60
UserA,LocationA,2018-01-01 09:00:00,60
UserA,LocationB,2018-01-01 10:00:00,60
UserA,LocationA,2018-01-01 11:00:00,60

解读:

样例数据中的数据含义是:
用户UserA,在LocationA位置,从8点开始,停留了60分钟
用户UserA,在LocationA位置,从9点开始,停留了60分钟
用户UserA,在LocationB位置,从10点开始,停留了60分钟
用户UserA,在LocationA位置,从11点开始,停留了60分钟

该样例期待输出:
UserA,LocationA,2018-01-01 08:00:00,120
UserA,LocationB,2018-01-01 10:00:00,60
UserA,LocationA,2018-01-01 11:00:00,60

处理逻辑:
1 对同一个用户,在同一个位置,连续的多条记录进行合并
2 合并原则:开始时间取最早时间,停留时长加和

要求:请使用Spark、MapReduce或其他分布式计算引擎处理

思路:按照按照用户ID和位置ID分组,分组之后按照时间列排序,由于数据之间的存在依赖关系,并且依赖关系比较连续,满足某种关系的数据要进行合并操作,因此使用sql部分的代码很难实现。在这使用的是将Dataset转化为RDD之后使用基于分区进行操作的方法处理数据。拿到相关的数据,按照时间顺序读取,判断,累加等进行处理。

 package com.zhf.streaming

 import java.text.SimpleDateFormat

 import org.apache.spark.Partitioner
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.{Dataset, SparkSession} import scala.collection.mutable.ArrayBuffer
case class ResultData(userID:String,locationID:String,startTime:String,endTime:String,stayTime:Long)
object Test {
def main(args: Array[String]): Unit = {
val spark = SparkSession.builder().appName("test").master("local[*]").getOrCreate()
import spark.implicits._
import org.apache.spark.sql.functions._
val info = spark.read
.format("csv")
.option("path", "src/data/user.csv")
.load()
.toDF("userID", "locationID", "startTimes", "stayMinutes")
.as[(String, String, String, String)] val ds: Dataset[((String, String, String), ResultData)] = info.map {
case (userID, locationID, startTimes, stayMinutes) =>
//让起始时间+停留时间=结束时间
val sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
val date = sd.parse(startTimes)
val endTime = sd.format(date.getTime + (stayMinutes.trim.toInt * 60 * 1000))
((userID, locationID, startTimes), ResultData(userID, locationID, startTimes, endTime, stayMinutes.trim.toLong))
}.as[((String, String, String), ResultData)] //按照用户ID和位置ID分组,分组之后按照时间列排序
val newDS: RDD[((String, String, String), ResultData)] = ds.rdd.repartitionAndSortWithinPartitions(new Partitioner {
override def numPartitions: Int = 4 override def getPartition(key: Any): Int = key match {
case (userID, locationID, _) => (userID.hashCode + locationID.hashCode) % numPartitions
case _ => 0
}
})
val result = newDS.mapPartitions(iter => {
val listBuffer = iter.toBuffer
val buffer = ArrayBuffer.empty[ResultData]
var resultData: ResultData = null;
//分区内只有一个元素的情况
if (listBuffer.size == 1) {
resultData = listBuffer(0)._2;
buffer += resultData
} else {
//分区内有多个元素
listBuffer.foreach {
case ((userID, locationID, startTimes), currentData) =>
//初始化赋值
if (resultData == null) {
resultData = ResultData(userID, locationID, startTimes, currentData.endTime, currentData.stayTime)
} else {
//如果当前行的起始时间与上一行的结束时间相同
if (currentData.startTime == resultData.endTime) {
//合并 修改初始值
resultData = ResultData(currentData.userID, currentData.locationID, resultData.startTime, currentData.endTime, resultData.stayTime + currentData.stayTime)
} else {
//不相同的情况下,将上一行结果添加到结果集,并修改初始值
buffer += resultData
resultData = currentData
}
}
}
//最后一个元素对象
if (resultData != null) {
buffer += resultData
}
}
buffer.toIterator
})
result.collect()
.sortBy(_.startTime)
.foreach(println)
}
}

使用spark dataSet 和rdd 解决 某个用户在某个地点待了多长时间的更多相关文章

  1. 解决使用Touch ID API在回调时界面“长时间卡住”的问题

    Touch ID是iOS8上新公开的API,关于详细介绍和用法可以看CocoaChina的这两篇文章:上 和 下,在此篇文章中不再赘述. 我在app中需要的效果是如果touch id验证通过,则页面p ...

  2. Spark SQL 之 RDD、DataFrame 和 Dataset 如何选择

    引言 Apache Spark 2.2 以及以上版本提供的三种 API - RDD.DataFrame 和 Dataset,它们都可以实现很多相同的数据处理,它们之间的性能差异如何,在什么情况下该选用 ...

  3. Spark计算模型-RDD介绍

    在Spark集群背后,有一个非常重要的分布式数据架构,即弹性分布式数据集(Resilient Distributed DataSet,RDD),它是逻辑集中的实体,在集群中的多台集群上进行数据分区.通 ...

  4. Spark学习之RDD编程总结

    Spark 对数据的核心抽象——弹性分布式数据集(Resilient Distributed Dataset,简称 RDD).RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外 ...

  5. 使用Scala编写Spark程序求基站下移动用户停留时长TopN

    使用Scala编写Spark程序求基站下移动用户停留时长TopN 1. 需求:根据手机基站日志计算停留时长的TopN 我们的手机之所以能够实现移动通信,是因为在全国各地有许许多多的基站,只要手机一开机 ...

  6. Spark深入之RDD

    目录 Part III. Low-Level APIs Resilient Distributed Datasets (RDDs) 1.介绍 2.RDD代码 3.KV RDD 4.RDD Join A ...

  7. Spark学习之RDD

    RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合 ...

  8. spark教程(三)-RDD认知与创建

    RDD 介绍 spark 最重要的一个概念叫 RDD,Resilient Distributed Dataset,弹性分布式数据集,它是 spark 的最基本的数据(也是计算)抽象. 代码中是一个抽象 ...

  9. Spark——DataFrames,RDD,DataSets、广播变量与累加器

    Spark--DataFrames,RDD,DataSets 一.弹性数据集(RDD) 创建RDD 1.1RDD的宽依赖和窄依赖 二.DataFrames 三.DataSets 四.什么时候使用Dat ...

随机推荐

  1. 个人永久性免费-Excel催化剂功能第103波-批量打开多文件或多链接

    有时简单的东西,却带来许多的便利,为了让大家可以记住并容易找寻到此功能,也将这么简单的功能归为一波,反正已经100+波了,也无需为了凑功能文章而故意罗列一些小功能带忽悠性地让人觉得很强大. 使用场景 ...

  2. HHyperledger Fabric 之 TLS (fabric-java-sdk)使用grpcs方式访问fabric

    我在很多fabric的技术群中,很多使用javasdk连接fabric的同友,初始的时候很多都没有成功的使用TLS进行区块链交易: 是sdk不支持,还是我们没有找到解决方案? 其实不然,我这里使用的是 ...

  3. vijos p1217 乒乓球

    注意数组越界.#include<iostream> #include<cmath> using namespace std; char letter[10001]; void ...

  4. [leetcode] 135. Candy (hard)

    原题 前后两遍遍历 class Solution { public: int candy(vector<int> &ratings) { vector<int> res ...

  5. C# Winform程序如何使用ClickOnce发布并自动升级(图解)

    有不少朋友问到C#Winform程序怎么样配置升级,怎么样打包,怎么样发布的,在这里我解释一下打包和发布关于打包的大家可以看我的文章C# winform程序怎么打包成安装项目(图解)其实打包是打包,发 ...

  6. python课堂整理4---列表的魔法

    一.list   类, 列表 li = [1, 12, 9, "age", ["大白", "小黑"], "alex"] ...

  7. 50 行 Python 代码,带你追到女神

    今天来给大家分享一个撩妹技巧,利用 python 每天给你最心爱的人,发送微信消息,说声晚安. 废话不多说,源代码奉上 def get_news(): ... url = "http://o ...

  8. linux初学者-正则表达式

      在windows中,是没有办法批量处理文件的,但是在linux系统中,可以通过命令直接处理一系列文件,这些文件的处理就需要用到正则表达式.这同样可以应用与目录. 1.处理多个文件 正则表达式中批量 ...

  9. spring 事务隔离级别导致的bug

    事情是这样的,ios进货单有一个数量加一手,减一手的功能,每加减一次就会异步调用后台的接口,后台判断sku如果不存在就插入,存在就更新.   问题描述: 当ios发了多次请求后, 在第二次请求的时候, ...

  10. 使用GDAL实现DEM的地貌晕渲图(三)

    目录 1. 原理 1) ArcMap生成彩色晕渲图 2) 彩色色带赋值 3) 颜色叠加 2. 实现 3. 结语 4. 参考 1. 原理 之前在<使用GDAL实现DEM的地貌晕渲图(一)>和 ...