Spark高级数据分析——纽约出租车轨迹的空间和时间数据分析
原文地址:https://www.jianshu.com/p/eb6f3e0c09b5
作者:IIGEOywq
一、地理空间分析:
object RunGeoTime extends Serializable {
val formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH)
def main(args: Array[String]): Unit = {
/*--------------1.初始化SparkContext-------------------*/
val sc = new SparkContext(new SparkConf().setAppName("SpaceGeo"))
/*--------------2.读取HDFS数据-------------------*/
val taxiRaw = sc.textFile("hdfs://master:9000/taxidata")
/*--------------3.出租车数据预处理------------------*/
//3.1 利用自定义的safe函数处理原始数据
val safeParse = safe(parse)
val taxiParsed = taxiRaw.map(safeParse)
//taxiParsed数据持久化
taxiParsed.cache()
//查看非法数据
/* val taxiBad = taxiParsed.collect({
case t if t.isRight => t.right.get
})*/
//collect返回到驱动器,为了单机开发和测试使用,不建议集群使用
//taxiBad.collect().foreach(println)
/*val taxiGood = taxiParsed.collect({
case t if t.isLeft => t.left.get
})
taxiGood.cache()*/
//3.2 剔除非法数据结果,获得正确格式的数据
val taxiGood=taxiParsed.filter(_.isLeft).map(_.left.get)
taxiGood.cache()
//自定义一次打车的乘坐时间函数
def hours(trip: Trip): Long = {
val d = new Duration(trip.pickupTime, trip.dropoffTime)
d.getStandardHours
}
//3.3 打印统计乘客上下车时间的记录,打印结果如执行分析结果图中的1
taxiGood.values.map(hours).countByValue().toList.sorted.foreach(println)
taxiParsed.unpersist()
//根据上面的输出结果,统计一次乘车时间大于0小于3小时的记录
val taxiClean = taxiGood.filter {
case (lic, trip) => {
val hrs = hours(trip)
0 <= hrs && hrs < 3
}
}
/*--------------4.出租车数据空间分析------------------*/
//4.1 获取纽约行政区划数据
val geojson = scala.io.Source.fromURL(getClass.getResource("/nyc-boroughs.geojson")).mkString
//转换为地理要素
val features = geojson.parseJson.convertTo[FeatureCollection]
val areaSortedFeatures = features.sortBy(f => {
val borough = f("boroughCode").convertTo[Int]
(borough, -f.geometry.area2D())
})
val bFeatures = sc.broadcast(areaSortedFeatures)
//4.2 判断乘客下车点落在那个行政区
def borough(trip: Trip): Option[String] = {
val feature: Option[Feature] = bFeatures.value.find(f => {
f.geometry.contains(trip.dropoffLoc)
})
feature.map(f => {
f("borough").convertTo[String]
})
}
//4.3 第一次统计打印各行政区下车点的记录,打印结果如执行分析结果图中的2
taxiClean.values.map(borough).countByValue().foreach(println)
//4.4 剔除起点和终点数据缺失的数据
def hasZero(trip: Trip): Boolean = {
val zero = new Point(0.0, 0.0)
(zero.equals(trip.pickupLoc) || zero.equals(trip.dropoffLoc))
}
val taxiDone = taxiClean.filter {
case (lic, trip) => !hasZero(trip)
}.cache()
//4.5 踢出零点数据后统计打印各行政区下车点的记录,打印结果如执行分析结果图中的3
taxiDone.values.map(borough).countByValue().foreach(println)
taxiGood.unpersist()
//输出地理空间分析结果到HDFS
//taxiDone.saveAsTextFile("hdfs://master:9000/GeoResult")
}
//字符串转double
def point(longitude: String, latitude: String): Point = {
new Point(longitude.toDouble, latitude.toDouble)
}
//获取taxiraw RDD记录中的出租车司机驾照和Trip对象
def parse(line: String): (String, Trip) = {
val fields = line.split(',')
val license = fields(1)
// Not thread-safe:
val formatterCopy = formatter.clone().asInstanceOf[SimpleDateFormat]
val pickupTime = new DateTime(formatterCopy.parse(fields(5)))
val dropoffTime = new DateTime(formatterCopy.parse(fields(6)))
val pickupLoc = point(fields(10), fields(11))
val dropoffLoc = point(fields(12), fields(13))
val trip = Trip(pickupTime, dropoffTime, pickupLoc, dropoffLoc)
(license, trip)
}
//非法记录数据处理函数
def safe[S, T](f: S => T): S => Either[T, (S, Exception)] = {
new Function[S, Either[T, (S, Exception)]] with Serializable {
def apply(s: S): Either[T, (S, Exception)] = {
try {
Left(f(s))
} catch {
case e: Exception => Right((s, e))
}
}
}
}
}
二、pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.cloudera.datascience.geotime</groupId>
<artifactId>ch08-geotime</artifactId>
<packaging>jar</packaging>
<name>Temporal and Geospatial Analysis</name>
<version>2.0.0</version>
<dependencies>
<!--注意 scala版本对应spark集群中scala的版本,provided属性要加上 -->
<dependency>
<groupId>org.scala-lang</groupId>
<artifactId>scala-library</artifactId>
<version>2.11.8</version>
<scope>provided</scope>
</dependency>
<!--注意 hadoop版本对应spark集群中hadoop的版本,provided属性要加上 -->
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>2.7.3</version>
<scope>provided</scope>
</dependency>
<!--注意 spark版本对应spark集群中spark的版本,2.11是对应的scala版本 -->
<dependency>
<groupId>org.apache.spark</groupId>
<artifactId>spark-core_2.11</artifactId>
<version>2.0.1</version>
<scope>provided</scope>
</dependency>
<!--nscala-time时间处理库,2.11是对应的scala版本 -->
<dependency>
<groupId>com.github.nscala-time</groupId>
<artifactId>nscala-time_2.11</artifactId>
<version>1.8.0</version>
</dependency>
<!--esri空间关系库,2.11是对应的scala版本 -->
<dependency>
<groupId>com.esri.geometry</groupId>
<artifactId>esri-geometry-api</artifactId>
<version>1.2.1</version>
</dependency>
<dependency>
<groupId>io.spray</groupId>
<artifactId>spray-json_2.11</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
<version>2.9.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<!--scala-maven插件必须加上,否则打包后无主程序 -->
<plugin>
<groupId>net.alchim31.maven</groupId>
<artifactId>scala-maven-plugin</artifactId>
<version>3.2.2</version>
<configuration>
<scalaVersion>2.11.8</scalaVersion>
<scalaCompatVersion>2.11.8</scalaCompatVersion>
<args>
<arg>-unchecked</arg>
<arg>-deprecation</arg>
<arg>-feature</arg>
</args>
<javacArgs>
<javacArg>-source</javacArg>
<javacArg>1.8.0</javacArg>
<javacArg>-target</javacArg>
<javacArg>1.8.0</javacArg>
</javacArgs>
</configuration>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!--maven-assembly插件可以打包应用的依赖包 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<archive>
<manifest>
<mainClass>com.cloudera.datascience.geotime.RunGeoTime</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<recompressZippedFiles>false</recompressZippedFiles>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- 用于maven继承项目的聚合 -->
<phase>package</phase> <!-- 绑定到package阶段 -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Spark高级数据分析——纽约出租车轨迹的空间和时间数据分析的更多相关文章
- SQL server 创建 修改表格 及表格基本增删改查 及 高级查询 及 (数学、字符串、日期时间)函数[转]
SQL server 创建 修改表格 及表格基本增删改查 及 高级查询 及 (数学.字符串.日期时间)函数 --创建表格 create table aa ( UserName varchar(50 ...
- 表空间基于时间点的恢复(TSPITR)
环境:RHEL 6.4 + Oracle 11.2.0.4 准备模拟环境 1. 验证表空间的依赖性 2. 确定执行TSPITR后会丢失的对象 3. 自动执行TSPITR Reference 准备模拟环 ...
- Redis学习笔记~关于空间换时间的查询案例
回到目录 空间与时间 空间换时间是在数据库中经常出现的术语,简单说就是把查询需要的条件进行索引的存储,然后查询时为O(1)的时间复杂度来快速获取数据,从而达到了使用空间存储来换快速的时间响应!对于re ...
- Redis基础知识之————空间换时间的查询案例
空间与时间 空间换时间是在数据库中经常出现的术语,简单说就是把查询需要的条件进行索引的存储,然后查询时为O(1)的时间复杂度来快速获取数据,从而达到了使用空间存储来换快速的时间响应!对于redis这个 ...
- 你好,C++(28)用空间换时间 5.2 内联函数 5.3 重载函数
5.2 内联函数 通过5.1节的学习我们知道,系统为了实现函数调用会做很多额外的幕后工作:保存现场.对参数进行赋值.恢复现场等等.如果函数在程序内被多次调用,且其本身比较短小,可以很快执行完毕,那么 ...
- 计数排序(O(n+k)的排序算法,空间换时间)
计数排序就是利用空间换时间,时间复杂度O(n+k) n是元素个数,k是最大数的个数: 统计每个数比他小的有多少,比如比a[i]小的有x个,那么a[i]应该排在x+1的位置 代码: /* * @Auth ...
- JDK1.8 LongAdder 空间换时间: 比AtomicLong还高效的无锁实现
我们知道,AtomicLong的实现方式是内部有个value 变量,当多线程并发自增,自减时,均通过CAS 指令从机器指令级别操作保证并发的原子性. // setup to use Unsafe.co ...
- flask 第四章 偏函数 Local空间转时间 myLocalStack RunFlask+request 请求上下文
1 . 偏函数 (partial) from functools import partial def func(*args,**kwargs): a=args b=kwargs return a,b ...
- Oracle之表空间基于时间点的恢复
记一次优化过程中:一次误操作,在不影响其他表空间的情况下:采用表空间基于时间点的恢复(TSPITR)方法恢复数据的过程. 1.TSPITR恢复原理 TSPITR目前最方便的方法是使用RMAN进行 ...
随机推荐
- Vue 面试题总结
1. Vue 框架的优点是什么? (1)轻量级框架:只关注视图层,大小只有几十Kb: (2)简单易学:文档通顺清晰,语法简单: (3)数据双向绑定,数据视图结构分离,仅需操作数据即可完 ...
- ShareSdk自己写的Demo
安卓原生Demo 根据mob发布的ShareSdk编写的demo,只添加了自己使用到的一些平台. 签名和第三方平台的账号都是用的shareSdk官方Demo的. 因为只是为了展示shareSdk用法, ...
- Sqoop(四)增量导入、全量导入、减量导入
增量导入 一.说明 当在生产环境中,我们可能会定期从与业务相关的关系型数据库向Hadoop导入数据,导入数仓后进行后续离线分析.这种情况下我们不可能将所有数据重新再导入一遍,所以此时需要数据增量导入. ...
- IE浏览器F12无法使用
原文链接http://zhhll.icu/2020/04/07/windows/IE%E6%B5%8F%E8%A7%88%E5%99%A8F12%E6%97%A0%E6%B3%95%E4%BD%BF% ...
- 【Sphinx】 为Python自动生成文档
sphinx 前言 Sphinx是一个可以用于Python的自动文档生成工具,可以自动的把docstring转换为文档,并支持多种输出格式包括html,latex,pdf等 开始 建一个存放文档的do ...
- 剑指offer 查找和排序的基本操作:查找排序算法大集合
重点 查找算法着重掌握:顺序查找.二分查找.哈希表查找.二叉排序树查找. 排序算法着重掌握:冒泡排序.插入排序.归并排序.快速排序. 顺序查找 算法说明 顺序查找适合于存储结构为顺序存储或链接存储的线 ...
- 1018 Public Bike Management (30分) PAT甲级真题 dijkstra + dfs
前言: 本题是我在浏览了柳神的代码后,记下的一次半转载式笔记,不经感叹柳神的强大orz,这里给出柳神的题解地址:https://blog.csdn.net/liuchuo/article/detail ...
- Maven学习笔记之第一个Maven项目(Linux)
Maven是Apache旗下的管理Java项目jar包的项目管理工具,有了它可以很方便构建和管理我们的Java项目,你不必在互联网上逐个查找你需要的第三方jar包,你只需在maven reposito ...
- kubernets之statefulset资源
一 了解Statefulset 1.1 对比statefulset与RS以及RC的区别以及相同点 Statefulset是有状态的,而RC以及RS等是没有状态的 Statefulset是有序的,拥 ...
- ctfhub技能树—密码口令—默认口令
打开靶机 查看页面内容 根据题目提示,去搜索北京亿中邮信息技术有限公司邮件网关的默认口令 尝试登录 成功拿到flag