Spark项目模拟——航班飞行网图分析

Spark项目模拟——航班飞行网图分析

需求描述

在这里插入图片描述

数据准备

数据文件一份,如下:

文件格式为CSV,字段之间分隔符为“,”

列依次为:#日、周#、航空公司、飞机注册号、航班号、起飞机场编号、起飞机场、到达机场编号、到达机场、预计起飞时间(时分)、起飞时间、起飞延迟(分钟)、到达预计时间、到达时间、到达延迟(分钟)、预计飞行时间、飞行距离

在这里插入图片描述

需求思路整理

创建属性图Graph[VD,ED]

1、装载CSV为RDD,每个机场作为顶点。关键字段:起飞机场编号、起飞机场、到达机场编号、到达机场、飞行距离

2、初始化顶点集airports:RDD[(VertexId,String)],顶点属性为机场名称

3、初始化边集lines:RDD[Edge],边属性为飞行距离

代码实现

import org.apache.spark.sql.types.{StringType, StructField, StructType}
import org.apache.spark.sql.types._
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.{SparkSession, types}
import org.apache.spark.graphx._
import org.apache.spark.rdd.RDD
import org.apache.spark.sql.types.StructType

object FlightDemo {
  def main(args: Array[String]): Unit = {
    val conf: SparkConf = new SparkConf().setAppName("etldemo").setMaster("local[*]")
    val spark: SparkSession = SparkSession.builder().config(conf).getOrCreate()
    val sc: SparkContext = spark.sparkContext

    import spark.implicits._
//加载文件
    val flightRDD: RDD[String] = sc.textFile("in/flight.csv")
//    flightRDD.collect().foreach(println)

    val airPort: RDD[(VertexId, String)] = flightRDD.map(x => x.split(","))
      .flatMap(x => Array((x(5).toLong, x(6)), (x(7).toLong, x(8))))
      .distinct()
//    airPort.collect().foreach(println)
//    println(airPort.count())    //机场数量

    val lines: RDD[Edge[PartitionID]] = flightRDD.map(x => x.split(",")) //(起飞机场编号,降落机场编号,飞行距离)
      .map(x => (x(5).toLong, x(7).toLong, x(16).toInt))
      .distinct()
      .map(x => Edge(x._1, x._2, x._3))
//    lines.collect().foreach(println)
//    println(lines.count())

    val graph = Graph(airPort,lines)
//    graph.triplets.collect().foreach(println)

    //机场数量
    val numvertices: VertexId = graph.numVertices
    println("机场数量"+numvertices)

    //航线数量
    val numedges: VertexId = graph.numEdges
    println("航线数量"+numedges)

    //计算最长的飞行航线
    val rdd1: RDD[EdgeTriplet[String, PartitionID]] = graph.triplets.sortBy(x=>x.attr,false)
    val str: Array[String] = rdd1.map(triplet => triplet.srcAttr + "   " + triplet.dstAttr + "  距离  :" + triplet.attr)
      .take(3)
//    str.foreach(println)

    
    //找出降落繁忙的机场
    val indegrees: VertexRDD[PartitionID] = graph.inDegrees
    val busyAirPort: (VertexId, PartitionID) = indegrees.sortBy(x=>x._2,false).take(1)(0)
//    println(busyAirPort)

    //找出起飞繁忙的机场
    val outdegrees: VertexRDD[PartitionID] = graph.outDegrees
    val busyinAirPort: (VertexId, PartitionID) = outdegrees.sortBy(x=>x._2,false).take(1)(0)
//    println(busyinAirPort)

    //找出最重要的飞行航线
    val vertices: VertexRDD[Double] = graph.pageRank(0.05).vertices
//    vertices.collect().foreach(println)
//    vertices.sortBy(x=>x._2).collect().foreach(println)

    //找出最便宜的飞行航线
    val value: RDD[(VertexId, String)] = airPort.sample(false,1.0/airPort.count(),1)
    val source_id=13930.toLong
    val srcAirPortName =value.first()._2
    val srcAirPortId= value.first()._1
    println(source_id,srcAirPortId,srcAirPortName)

    val init_graph: Graph[Double, Double] = graph.mapVertices((id, value) => {
      if (id == srcAirPortId) 0
      else Double.PositiveInfinity
    }).mapEdges(e=> 180 + 0.15*e.attr.toDouble)


    val pregel_graph: Graph[Double, Double] = init_graph.pregel(
      Double.PositiveInfinity,
      Int.MaxValue,
      EdgeDirection.Out
    )(
      (id, dist, new_dist) => math.min(dist, new_dist),
      triple => {
        if (triple.attr + triple.srcAttr < triple.dstAttr)
          Iterator((triple.dstId, triple.attr + triple.srcAttr))
        else
          Iterator.empty
      },
      (dist, new_dist) => math.min(dist, new_dist)
    )
    pregel_graph.triplets.collect().foreach(println)
    //((16218,906.15),(12892,748.05),215.55)
    // 初始机场13296  到 16218  最低费用为 906.15
    //初始机场 13296   到12892   最低费用为748.05
    //机场16218  到12892  最低费用为 215.55




    //得到 初始机场到 另一个机场的 最少费用
//    pregel_graph.vertices.collect().foreach(println)


    //最便宜的机票
//    val tuples: Array[(VertexId, Double)] = pregel_graph.vertices.sortBy(x=>x._2).take(3)
//    println(tuples.toList)

    //List((13296,0.0), (12953,209.25), (11618,211.35))
    //13296 为初始机场,所以费用为0

  }
}

总结

实现需求过程中使用了以下函数:

Spark GraphX API
    vertices、edges、triplets、
	numEdges、numVertices
	inDegrees、outDegrees、degrees
	mapVertices、mapEdges、mapTriplets
	
Spark GraphX PageRank

Spark GraphX Pregel

机场数量:

求顶点个数:Graph.numVertices

航线数量:

求边的个数:Graph.numEdges

最大的边属性:

对triplets按飞行距离排序(降序)并取第一个

哪个机场到达航班最多:

计算顶点的入度并排序

找出最重要的飞行航线:

PageRank
收敛误差:0.05

找出最便宜的飞行航线:

定价模型:
price = 180.0 + distance * 0.15

SSSP问题 :
从初始指定的源点到达任意点的最短距离

pregel:
1、初始化源点(0)与其它顶点(Double.PositiveInfinity)
2、初始消息(Double.PositiveInfinity)
3、vprog函数计算最小值
4、sendMsg函数计算进行是否下一个迭代
5、mergeMsg函数合并接受的消息,取最小值

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值