使用spark dataSet 和rdd 解决 某个用户在某个地点待了多长时间
现有如下数据文件需要处理
格式: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 解决 某个用户在某个地点待了多长时间的更多相关文章
- 解决使用Touch ID API在回调时界面“长时间卡住”的问题
Touch ID是iOS8上新公开的API,关于详细介绍和用法可以看CocoaChina的这两篇文章:上 和 下,在此篇文章中不再赘述. 我在app中需要的效果是如果touch id验证通过,则页面p ...
- Spark SQL 之 RDD、DataFrame 和 Dataset 如何选择
引言 Apache Spark 2.2 以及以上版本提供的三种 API - RDD.DataFrame 和 Dataset,它们都可以实现很多相同的数据处理,它们之间的性能差异如何,在什么情况下该选用 ...
- Spark计算模型-RDD介绍
在Spark集群背后,有一个非常重要的分布式数据架构,即弹性分布式数据集(Resilient Distributed DataSet,RDD),它是逻辑集中的实体,在集群中的多台集群上进行数据分区.通 ...
- Spark学习之RDD编程总结
Spark 对数据的核心抽象——弹性分布式数据集(Resilient Distributed Dataset,简称 RDD).RDD 其实就是分布式的元素集合.在 Spark 中,对数据的所有操作不外 ...
- 使用Scala编写Spark程序求基站下移动用户停留时长TopN
使用Scala编写Spark程序求基站下移动用户停留时长TopN 1. 需求:根据手机基站日志计算停留时长的TopN 我们的手机之所以能够实现移动通信,是因为在全国各地有许许多多的基站,只要手机一开机 ...
- Spark深入之RDD
目录 Part III. Low-Level APIs Resilient Distributed Datasets (RDDs) 1.介绍 2.RDD代码 3.KV RDD 4.RDD Join A ...
- Spark学习之RDD
RDD概述 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的集合 ...
- spark教程(三)-RDD认知与创建
RDD 介绍 spark 最重要的一个概念叫 RDD,Resilient Distributed Dataset,弹性分布式数据集,它是 spark 的最基本的数据(也是计算)抽象. 代码中是一个抽象 ...
- Spark——DataFrames,RDD,DataSets、广播变量与累加器
Spark--DataFrames,RDD,DataSets 一.弹性数据集(RDD) 创建RDD 1.1RDD的宽依赖和窄依赖 二.DataFrames 三.DataSets 四.什么时候使用Dat ...
随机推荐
- GeoPackage - 一个简便轻量的本地地理数据库
GeoPackage(以下简称gpkg),内部使用SQLite实现的一种单文件.与操作系统无关的地理数据库. 当前标准是1.2.1,该版本的html版说明书:https://www.geopackag ...
- 在C#中ParameterizedThreadStart和ThreadStart区别
不需要传递参数,也不需要返回参数 我们知道启动一个线程最直观的办法是使用Thread类,具体步骤如下: ThreadStart threadStart=new ThreadStart(Calculat ...
- Java EE.JSP.概述
JSP最终会被转换成标准Servlet,该转换过程一般出现在第一次请求页面时. JSP页面的主要组成部分如下: HTML 脚本:嵌入Java代码 指令:从整体上控制Servlet的结构 动作:引入现有 ...
- Webpack打包效率优化篇
Webpack基础配置: 语法解析:babel-loader 样式解析:style-loader css解析:css-loader less解析:less-loader 文件解析:url-loader ...
- 算法-一步步教你如何用c语言实现堆排序(非递归)
看了左神的堆排序,觉得思路很清晰,比常见的递归的堆排序要更容易理解,所以自己整理了一下笔记,带大家一步步实现堆排序算法 首先介绍什么是大根堆:每一个子树的最大值都是子树的头结点,即根结点是所有结点的最 ...
- UML同一建模语言
结构型图:描述系统静态结构,显示系统类之间的静态关系. 行为型图:描述系统的动态属性,显示系统元素如何协作产生满足要求的系统行为. 类图分类名,属性清单,方法清单,性质清单几层 类之间的关系:1 一般 ...
- Prometheus 整合 AlertManager
简介 Alertmanager 主要用于接收 Prometheus 发送的告警信息,它很容易做到告警信息的去重,降噪,分组,策略路由,是一款前卫的告警通知系统.它支持丰富的告警通知渠道,可以将告警信息 ...
- 微信小程序的尺寸单位rpx介绍
rpx单位是微信小程序中css的尺寸单位,rpx可以根据屏幕宽度进行自适应. 规定屏幕宽为750rpx.如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375 ...
- UE4 游戏模块初始化顺序
最近看教学,有个讲解UE4初始化顺序的,记录一下. 首先创建一个Actor,Character,GameInstance,GameMode,LevelScriptActor(关卡),PlayerCon ...
- Java课堂 动手动脑5
1.了解棋盘打印:利用二维数组输出一个15*15的棋盘,棋盘的原素为“+”,就是输出一个横纵都是15个“+”的二维数组,然后再以坐标形式输入棋子“●”,替换掉原来棋盘里的“+”.再编写代码. 电脑随机 ...