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进行 ...
随机推荐
- Hbase集群模式搭建
1.官网下载hbase安装包 这里不做赘述. 2.解压---直接tar -zxvf xxxx 3.配置hbase集群,要修改3个文件(首先zk集群已经安装好了) 注意:要把hadoop的hdfs-si ...
- excel字符串拼接
函数:CONCATENATE() 参数可以是文本值.数字或单元格引用. 文本值和数字使用双引号括住,单元格引用直接使用.例如 =CONCATENATE("abc",A2),设A2为 ...
- Spring Boot 2.x基础教程:实现文件上传
文件上传的功能实现是我们做Web应用时候最为常见的应用场景,比如:实现头像的上传,Excel文件数据的导入等功能,都需要我们先实现文件的上传,然后再做图片的裁剪,excel数据的解析入库等后续操作. ...
- [新手教程]申请https泛域名解析
前置准备 教程开始,我们默认相信小伙伴们对基本的域名购买及解析有了一定的认识和实践 一个正常的域名 一台公网服务器 域名解析操作 如:现在我们要设置frps的泛域名解析 设置二级域名 frp.xx.c ...
- 项目实战--@Transactional 的使用
@Transactional 介绍 Spring 事务管理分为编码式和声明式的两种方式,编程式事务指的是通过编码方式实现事务:声明式事务基于 AOP,将具体业务逻辑与事务处理解耦.@Transacti ...
- laravel邮件发送
laravel邮件发送 使用邮件发送类Mail 文本 静态方法 raw() 富文本 静态方法 send() 注:使用邮件发送必须有邮件账号,需要开启smtp协议,现在主流服务器都支持,smtp默认端口 ...
- SonarQube学习(五)- SonarQube之自定义规则使用
一.前言 古人云:"欲速则不达",最近真的是深有体会.学习也是如此,不是一件着急的事,越是着急越不会. 就拿SonarQube来说吧,去年年末就想学来着,但是想着想着就搁置了,有时 ...
- 【EXP】导出数据库dmp文件,只有几张表有数据,剩下的所有表只有表结构没有数据
导出一个dmp,指定的表中有数据,其他的表只有表结构, 有数据的表只有几张,分别是A,B,C三张表,剩下的表都没有数据 思路: 导出一个111.dmp,所有的表都只是表结构 将111.dmp导入到新创 ...
- CTFshow-萌新赛web_假赛生
打开靶机 网页源码提示代码如下 根据提示,存在 login.php register.php,根据要求需要用户名为admin,尝试注册后发现已存在,接着尝试注册用户名admin+空格,接着用admin ...
- oracle rac切换到单实例DG后OGG的处理
在RAC切换到单实例DG后,将OGG目录复制过去,在使用alter extract ext_name,begin now的时候报错 2016-04-10 11:27:03 WARNING OGG-01 ...