我正在试验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))
然后从那里开始,我不知道如何在加权的单一图形中对其进行转换。
答案 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"))
这可以转换为Graph
或GraphFrame
,如我在此处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"))
然后,您可以使用消息传递或图形模式匹配来查找两个跃点邻居。