GraphX【算法实现】 同配性算法:平均相邻度算法

该算法用于分析图数据结构中每个节点的邻域平均度数,探讨节点是否倾向于与度数相近的其他节点相连。它使用Spark的GraphX库,根据给定的边方向计算节点的度数,然后计算每个节点的邻点的平均度数。如果提供了特定节点列表,则仅分析这些节点。
摘要由CSDN通过智能技术生成

算法描述:

计算每个节点邻域的平均度数。用作考察度数相近的节点是否倾向于相互连接,在社交网络中,节点更倾向于与度数相近的节点相连。

实现逻辑

/**
*  @param g: 待分析图:GraphX图结构
* @param  sourceDirection:作用与原定点的方向取值为:In | Out 默认值为:Out
* @param targetDirection: 作用与目标顶点的方向,取值为:In |Out 默认值为:Out
* @param nodeList : 待分析顶点列表,默认值为null,如果为null,则分析全图
*/
def averageNeighborsDegree[VD, ED: ClassTag](g: Graph[VD, ED],
                                               sourceDirection: EdgeDirection = EdgeDirection.Out,
                                               targetDirection: EdgeDirection = EdgeDirection.Out,
                                               nodeList: List[VertexId] = null): RDD[(VertexId, Double)] = {

    val graph = g.cache()
    //根据sourceDirection|targetDirection,计算每个点的度数
    val sourceDegree: VertexRDD[Int] = degreesRDD(graph, sourceDirection)
    val targetDegree: Array[(Long, Int)] = degreesRDD(graph, targetDirection).collect()
    val sc = SparkSession.builder().getOrCreate().sparkContext
    val broadcast = sc.broadcast(targetDegree)
    //如果指定了节点列表,则过滤指定的节点列
    val sourceNodes: VertexRDD[Int] = if (nodeList == null) {
      sourceDegree.filter(item => nodeList.contains(item._1))
    } else {
      sourceDegree
    }

    //计算每个节点的邻点列表
    val neighbor: VertexRDD[Set[VertexId]] = neighbors(graph, targetDirection).cache()

    val vertexNeighborsRDD: RDD[(VertexId, (Int, Option[Set[VertexId]]))] = sourceNodes.leftOuterJoin(neighbor)

    val result: RDD[(VertexId, Double)] = vertexNeighborsRDD.map(item => {
      val deg = if (item._2._1 == 0) 1 else item._2._1
      //过滤出当前节点的邻点集
      val itemNeighbors: Set[VertexId] = item._2._2.getOrElse(Set())
      // 如果邻点节点不为空,则计算该邻点节点的度数之和
      if (itemNeighbors.nonEmpty) {
        val neighborDegree: Double = broadcast.value.filter(itemV2 => itemNeighbors.contains(itemV2._1)).map(_._2).sum
        val avg = neighborDegree / deg
        (item._1, avg)
      } else {
        (item._1, 0)
      }
    })

    result

  }
  /**
   * 计算图中每个顶点的邻点集
   */
  def neighbors[VD, ED: ClassTag](graph: Graph[VD, ED],
                                  edgeDirection: EdgeDirection = EdgeDirection.Either): VertexRDD[Set[VertexId]] = {
    if (edgeDirection == EdgeDirection.In) {
      graph.aggregateMessages(ctx => {
        ctx.sendToDst(Set(ctx.srcId))
      }, _ ++ _, TripletFields.None)
    } else if (edgeDirection == EdgeDirection.Out) {
      graph.aggregateMessages(ctx => {
        ctx.sendToSrc(Set(ctx.dstId))
      }, _ ++ _, TripletFields.None)
    }
    else {
      graph.aggregateMessages(ctx => {
        ctx.sendToDst(Set(ctx.srcId))
        ctx.sendToSrc(Set(ctx.dstId))
      }, _ ++ _, TripletFields.None)
    }
  }
  
  def degreesRDD[VD: ClassTag, ED: ClassTag](g: Graph[VD, ED],
                                             direction: EdgeDirection = EdgeDirection.Either): VertexRDD[Int] = {
    val vertexRdd: VertexRDD[Int] = direction match {
      case EdgeDirection.In => g.inDegrees
      case EdgeDirection.Out => g.outDegrees
      case EdgeDirection.Either => g.degrees
      case EdgeDirection.Both =>
        throw new SparkException("collectEdges does not support EdgeDirection.Both.Use EdgeDirection.Either instead")
    }
    vertexRdd
  }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

stay_running

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值