使用GraphX从二分网络创建单独的图形

时间:2018-01-07 10:34:17

标签: scala apache-spark graph rdd spark-graphx

我正在试验Spark,我是Scala和GraphX的新手。

我正在制作一个电影和演员的双网网络。 我的输入是一个空格分隔的文件,每行有一个边,第一列是电影ID,第二列是演员ID,这是一个提取:

movie actor
1 1 
2 1 
2 2 
3 1 
3 3 
3 4 
3 5 
3 6 
3 7 
4 1 

我的目标是研究演员之间的关系。为此,我想创建一个单独的图形actor-actor,它根据这些角色的公共电影数量来限制值。

我首先创建一个边缘的RDD:

val edges: RDD[Edge[String]] = sc.textFile("file:///home/actorMovie").map { line =>
    val fields = line.split(" ")
    Edge(fields(0).toLong, fields(1).toLong)
  }

看起来不错:

edges.take(10)
res8: Array[org.apache.spark.graphx.Edge[String]] = Array(Edge(1,1,null), Edge(2,1,null), Edge(2,2,null), Edge(3,1,null), Edge(3,3,null), Edge(3,4,null), Edge(3,5,null), Edge(3,6,null), Edge(3,7,null), Edge(4,1,null))

然后从那里开始,我不知道如何在加权的单一图形中对其进行转换。

1 个答案:

答案 0 :(得分:2)

你现在拥有的不是二分图。要使它成为有效的图形,您必须进行大量的转换。最简单的方法是使用数据帧:

val df = spark.read
  .option("delimiter", " ") // if there is a header
  .option("header", "true")
  .csv(path)
  .toDF("movie", "actor")

一旦你有数据自我加入并像这样聚合:

import org.apache.spark.sql.functions._

val e = df.alias("df1")
  .join(df.alias("df2"), "movie")
  // Sort soruce and destination
  .groupBy(
     greatest("df1.actor", "df2.actor").as("srcId"), 
     least("df1.actor", "df2.actor").as("dstId"))
  .agg(count("*").as("attr"))

这可以转换为GraphGraphFrame,如我在此处How to obtain convert DataFrame to specific RDD?所示。

要创建有效图表,您必须对标签进行编码。例如:

val dfe = df.select(
  concat(lit("m"), $"movie").as("movie"),
  concat(lit("a"), $"actor").as("actor"))

然后,您可以按How to encode string values into numeric values in Spark DataFrame中的说明应用StringIndexer或使用GraphFrame自动执行此操作:

import graphframes._

val gf = GraphFrame.fromEdges(dfe.toDF("src", "dst"))

然后,您可以使用消息传递或图形模式匹配来查找两个跃点邻居。