Scala 删除GraphX中没有传出边的顶点

Scala 删除GraphX中没有传出边的顶点,scala,apache-spark,spark-graphx,Scala,Apache Spark,Spark Graphx,我有一个大图(几百万个顶点和边)。我要删除所有没有传出边的顶点(&边)。我有一些代码,但它是缓慢的,我需要做几次。我相信我可以使用一些现有的GraphX方法来加快速度 这是我的密码 val users: RDD[(VertexId, String)] = sc.parallelize(Array((1L, "1"), (2L, "2"), (3L, "3"), (4L, "4"))) val relationships: RDD[Edge[Double]] = sc.parallelize(

我有一个大图(几百万个顶点和边)。我要删除所有没有传出边的顶点(&边)。我有一些代码,但它是缓慢的,我需要做几次。我相信我可以使用一些现有的GraphX方法来加快速度

这是我的密码

val users: RDD[(VertexId, String)] = sc.parallelize(Array((1L, "1"), (2L, "2"), (3L, "3"), (4L, "4")))
  val relationships: RDD[Edge[Double]] = sc.parallelize(
    Array(
      Edge(1L, 3L, 500.0),
      Edge(3L, 2L, 400.0),
      Edge(2L, 1L, 600.0),
      Edge(3L, 1L, 200.0),
      Edge(2L, 4L, 200.0),
      Edge(3L, 4L, 500.0)
    ))

val graph = org.apache.spark.graphx.Graph(users, relationships)

val lst = graph.outDegrees.map(x => x._1).collect
var set:scala.collection.mutable.HashSet[Long] = new scala.collection.mutable.HashSet()
for(a<- lst) {set.add(a)}
var subg = graph.subgraph(vpred = (id, attr) => set.contains(id))
//since vertex 4 has no outgoing edges, subg.edges should return 4 and subg.vertices = 3 
val用户:RDD[(VertexId,String)]=sc.parallelize(数组((1L,“1”),(2L,“2”),(3L,“3”),(4L,“4”))
val关系:RDD[Edge[Double]=sc.parallelize(
排列(
边缘(1L、3L、500.0),
边缘(3L、2L、400.0),
边缘(2L、1L、600.0),
边缘(3L、1L、200.0),
边缘(2L、4L、200.0),
边缘(3L、4L、500.0)
))
val graph=org.apache.spark.graphx.graph(用户、关系)
vallst=graph.outDegrees.map(x=>x.\u 1).collect
变量集:scala.collection.mutable.HashSet[Long]=新的scala.collection.mutable.HashSet()
对于(集合包含(id))
//由于顶点4没有传出边,因此subg.edges应返回4,并且subg.vertexs=3
我不知道还有什么别的办法可以做到。感谢您的帮助


编辑:我可以用HashSet来做,但我认为它仍然可以改进。

对代码的第一个优化是将lst设置为集合而不是数组,这将使查找成为O(1)而不是O(n)


但这是不可伸缩的,因为您正在收集驱动程序上的所有内容,然后将其发送回执行器。正确的方法是使用
outDegrees
调用
joinVertices
,只需映射到原始图形。

您可以使用过滤的顶点直接定义另一个图形。 大概是这样的:

val lst = graph.outDegrees.map(x => x._1).collect
var graph2 = Graph(graph.vertices.filter(v => lst.contains(v)), graph.edges)

如果您不想使用子图,下面是另一种使用三元组查找目标顶点(也是源顶点)的方法

val graph = org.apache.spark.graphx.Graph(users, relationships)
val AsSubjects = graph.triplets.map(triplet => (triplet.srcId,(triplet)))
val AsObjects = graph.triplets.map(triplet => (triplet.dstId,(triplet)))
val ObjectsJoinSubjects = AsObjects.join(AsSubjects)
val ObjectsJoinSubjectsDistinct = ObjectsJoinSubjects.mapValues(x => x._1).distinct()
val NewVertices = ObjectsJoinSubjectsDistinct.map(x => (x._2.srcId, x._2.srcAttr)).distinct()
val NewEdges = ObjectsJoinSubjectsDistinct.map(x => new Edge(x._2.srcId, x._2.dstId, x._2.attr))
val newgraph = Graph(NewVertices,NewEdges)

我不确定这是否比子图有所改进,因为我的解决方案使用了distinct(),这很昂贵。我使用您提供的图表进行了测试,我的解决方案实际上需要更长的时间。不过,我觉得这只是一个小例子。因此,我建议您使用一个更大的图表进行测试,并让我们知道这是否更好。

您可以通过这个来找到所有的零度超差

val zeroOutDeg = graph.filter(graph => {
   val degrees: VertexRDD[Int] = graph.outDegrees
   graph.outerJoinVertices(degrees) {(vid, data, deg => deg.getOrElse(0)}
   }, vpred = (vid: VertexId, deg:Int) => deg == 0)

谢谢你的意见。我试着用HashSet来做,但没用。你能举一个例子,我如何用连接顶点来实现它吗?顺便说一句,JoinVertices不是内部连接。