使用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 ...
随机推荐
- [小米OJ] 5. 找出旋转有序数列的中间值
排序,输出 #include <bits/stdc++.h> using namespace std; int main() { string input; while (cin > ...
- [leetcode]95 Unique Binary Search Trees II (Medium)
原题 字母题添加链接描述 一开始完全没有思路.. 百度看了别人的思路,对于这种递归构造的题目还是不熟,得多做做了. 这个题目难在构造出来.一般构造树都需要递归. 从1–n中任意选择一个数当做根节点,所 ...
- 用python输出回文数
一个b站上的朋友问我,怎么返回五位数的回文数的个数. 我首先百度回文数的概念,就是正读和倒读都一样的数字,例如:10001,99899 等等 数字的位数拆分一头雾水,思来想去,用字符串的方法完美解决! ...
- 高级查询MYsql(二) 练习
一.单词部分 ①exist存在②temp临时的③district区域 ④content内容⑤temporary暂时的 二.预习部分 1.表连接都可以用子查询替换吗 是的 2.检测某列是否存在某个范围可 ...
- Android 开发环境之 VMware 虚拟机(android8.1)
VM版本14 在官网下载androidx86的VMDK文件 官方下载地址 (VMDK文件是VMware的专用文件,比iso镜像文件安装要简便许多,内部已经配置好了,只需要按照虚拟机安装普通流程即可) ...
- HttpsUtils
package io.renren.modules.jqr.util; import java.io.BufferedReader; import java.io.InputStream; impor ...
- Java内部类超详细总结(含代码示例)
什么是内部类 什么是内部类? 顾名思义,就是将一个类的定义放在另一个类的内部. 概念很清楚,感觉很简单,其实关键在于这个内部类放置的位置,可以是一个类的作用域范围.一个方法的或是一个代码块的作用域范围 ...
- java高并发系列 - 第22天:java中底层工具类Unsafe,高手必须要了解
这是java高并发系列第22篇文章,文章基于jdk1.8环境. 本文主要内容 基本介绍. 通过反射获取Unsafe实例 Unsafe中的CAS操作 Unsafe中原子操作相关方法介绍 Unsafe中线 ...
- Serilog 自定义Enricher 来增加记录的信息
Serilog 自定义Enricher 来增加记录的信息 Intro Serilog 是 .net 里面非常不错的记录日志的库,结构化日志记录,而且配置起来很方便,自定义扩展也很方便 Serilog ...
- LeetCode——409. Longest Palindrome
题目: Given a string which consists of lowercase or uppercase letters, find the length of the longest ...