航空数据简单计算
数据格式
dom – 月中第几天 (day of month)
dow – 周中第几天 (day of week)
carrier – 航空公司
tail_num – 飞机注册号
fl_num – 航班号
origin_id – 起飞机场编号
origin – 起飞机场
dest_id – 到达机场编号
dest – 到达机场
crs_dep_time – 预计起飞时间
dep_time – 起飞时间
dep_delay_mins – 起飞延迟 (分钟)
crs_arr_time – 预计到达时间
arr_time – 到达时间
arr_delay_mins – 到达延迟 (分钟)
crs_elapse_time – 预计飞行时间
dist – 飞行距离
这是其中一小部分数据,充当演示数据格式的作用,不是全部数据
项目要求
- 统计航班飞行网图中机场的数量
- 统计航班飞行网图中航线的数量
- 计算最长的飞行航线(Point to Point)
- 找出最繁忙的机场
- 找出最重要的飞行航线(PageRank)
- 找出最便宜的飞行航线
基本代码
//模板代码
private val spark: SparkSession = SparkSession.builder()
.appName(this.getClass.getSimpleName)
.master("local[*]")
.getOrCreate()
private val sc: SparkContext = spark.sparkContext
//加载数据
private val flights: RDD[Array[String]] =
sc.textFile("src/main/scala/cn8/Test2/plane.csv")
.mapPartitionsWithIndex((index, iter) =>
if (index == 0) iter.drop(1) else iter)
.map(_.split(","))
.cache()
//点集合
private val airports: RDD[(Long, String)] =
flights.flatMap(x => Array((x(5).toLong, x(6)), (x(7).toLong, x(8)))).distinct()
//边集合
private val lines: RDD[Edge[Int]] =
flights.map(x => (x(5).toLong, x(7).toLong, x(16).toInt))
.distinct().map(x => Edge(x._1, x._2, x._3))
//构建图
private val graph: Graph[String, Int] = Graph(airports, lines)
1.统计机场数量
实际上就是找出顶点的个数
println("机场数量 : " + graph.numVertices)
2.统计航线的数量
实际上就是找出边的数量
println("航线数量 : " + graph.numEdges)
3. 计算最长的飞行航线
可以通过 起飞机场 和 降落机场 及 其中的参数进行判断
graph.triplets.sortBy(_.attr, false).take(1)
.map(x => "航线距离最长 : " + x.srcAttr + "---->" + x.dstAttr + "----距离 : " + x.attr)
.foreach(println)
4.最繁忙的机场
即找到 入度 和 出度 数量最多的 点
//入度
graph.inDegrees
.sortBy(_._2, false)
.take(1)
.foreach(x => println("入度最多机场 : " + x))
//出度
graph.outDegrees
.sortBy(_._2, false)
.take(1)
.foreach(x => println("出度最多机场 : " + x))
5.最重要的机场
需要通过PageRank进行权重排序
graph.pageRank(0.05).vertices.join(airports)
.sortBy(_._2._1, false)
.take(3)
.map(x => (x._2._2, x._2._1))
.foreach(println)
6.最便宜的飞行路线
计算公式 : price = 180.0 + distance * 0.15
//取得一个点作为原点,可随机设置,也可以手动设置
//此处使用手动设置,机场编号12478
val source_id: VertexId = 12478
//初始化一个图,包括点和边
private val init_graph: Graph[Double, Double] =
graph.mapVertices((id, _) =>
if (id == source_id) 0.0 else Double.PositiveInfinity)
.mapEdges(e => e.attr.toDouble * 0.15)
//这里需要使用到pregel方法,需要事先定义 接受消息 发送消息 合并消息 三个值
//接受消息
val f1: (VertexId, Double, Double) => Double =
(id, dist, new_dist) => math.min(dist, new_dist)
//(筛选)发送消息
val f2: EdgeTriplet[Double, Double] => Iterator[(VertexId, Double)] = triplet =>
{
if (triplet.srcAttr + triplet.attr < triplet.dstAttr)
Iterator((triplet.dstId,triplet.srcAttr + triplet.attr))
else
Iterator.empty
}
//合并
val f3: (Double, Double) => Double = (x, y) => math.min(x, y)
//调用pregel函数进行计算
val pregel_graph: Graph[Double, Double] =
init_graph.pregel(Double.PositiveInfinity)(f1, f2, f3)
//输出
pregel_graph.vertices.filter(x => x._2 != 0).takeOrdered(1)
{
Ordering.by(x => x._2)
}.foreach(x => println(s"从$source_id 出发到 ${x._1}最便宜的价格为: ${x._2}"))