使用 GraphX 从二分网络创建单分图
Creating unipartite graph from bipartite network with GraphX
我正在试验 Spark,我是 Scala 和 GraphX 的新手。
我正在研究一个由电影和其中的演员组成的双向网络。
我的输入是一个 space 分隔的文件,每行一条边,第一列是电影 ID,第二列是演员 ID,这里是摘录:
movie actor
1 1
2 1
2 2
3 1
3 3
3 4
3 5
3 6
3 7
4 1
我的目标是研究演员之间的关系。为此,我想创建一个单分图演员-演员,其边缘值取决于这些演员的常见电影数量。
我首先创建一个边 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))
然后从那里开始,我不知道如何将其转换为加权单部图。
您现在拥有的不是二分图。要使其成为有效的图形,您必须进行大量转换。最简单的方法是使用数据帧:
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
,正如我在此处显示的那样 。
要创建有效的图表,您必须对标签进行编码。例如:
val dfe = df.select(
concat(lit("m"), $"movie").as("movie"),
concat(lit("a"), $"actor").as("actor"))
然后您可以按照 or use GraphFrame
中的说明应用 StringIndexer
来自动执行此操作:
import graphframes._
val gf = GraphFrame.fromEdges(dfe.toDF("src", "dst"))
然后你可以使用消息传递或图形模式匹配来找到两跳邻居。
我正在试验 Spark,我是 Scala 和 GraphX 的新手。
我正在研究一个由电影和其中的演员组成的双向网络。 我的输入是一个 space 分隔的文件,每行一条边,第一列是电影 ID,第二列是演员 ID,这里是摘录:
movie actor
1 1
2 1
2 2
3 1
3 3
3 4
3 5
3 6
3 7
4 1
我的目标是研究演员之间的关系。为此,我想创建一个单分图演员-演员,其边缘值取决于这些演员的常见电影数量。
我首先创建一个边 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))
然后从那里开始,我不知道如何将其转换为加权单部图。
您现在拥有的不是二分图。要使其成为有效的图形,您必须进行大量转换。最简单的方法是使用数据帧:
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
,正如我在此处显示的那样
要创建有效的图表,您必须对标签进行编码。例如:
val dfe = df.select(
concat(lit("m"), $"movie").as("movie"),
concat(lit("a"), $"actor").as("actor"))
然后您可以按照 GraphFrame
中的说明应用 StringIndexer
来自动执行此操作:
import graphframes._
val gf = GraphFrame.fromEdges(dfe.toDF("src", "dst"))
然后你可以使用消息传递或图形模式匹配来找到两跳邻居。