我正在测试graphframes BFS玩具示例:
val g: GraphFrame = examples.Graphs.friends
val paths: DataFrame = g.bfs.fromExpr("name = 'Esther'").toExpr("name <> 'Esther'").run()
我得到的结果是:
+-------------+------------+------------+
| from| e0| to|
+-------------+------------+------------+
|[e,Esther,32]|[e,f,follow]|[f,Fanny,36]|
|[e,Esther,32]|[e,d,friend]|[d,David,29]|
+-------------+------------+------------+
这很奇怪,因为范妮和大卫也有外向的缘故。并且链接到它们的顶点也具有输出边缘,例如,结果数据帧不仅应包含一个跳跃路径,而且应包含来自源顶点的所有路径。
我自己创建了一个玩具图表:
1 2
2 3
3 4
4 5
当我做同样的查询时:
g.bfs.fromExpr("id = 1").toExpr("id <> 1").run()
我仍然只得到一跳邻居。我错过了什么吗?我还测试了其他代表&#34;不等于&#34;没有成功。一个疯狂的猜测:也许当BFS再次到达源顶点时(它应该看它,但不能访问它的邻居),它与&#34; toExpr&#34;表达和中止。
另一个问题:GraphFrames是针对性的,不是吗?为了获得&#34;非直接图表&#34;,我应该添加倒数边缘,不应该是吗?
答案 0 :(得分:0)
到达范妮和大卫后,你找到了从埃斯特到非埃斯特节点的最短路径,所以搜索停止了。
根据GraphFrames User Guide,bfs
方法“找到从一个顶点(或一组顶点)到另一个顶点(或一组顶点)的最短路径。和结束顶点被指定为Spark DataFrame表达式。“
在你正在使用的图表中,从Esther到非Esther节点的最短路径只是一跳,因此广度优先搜索就会停止。
考虑您的数字玩具图表。你找到了这个(一跳):
import org.graphframes.GraphFrame
val edgesDf = spark.sqlContext.createDataFrame(Seq(
(1, 2),
(2, 3),
(3, 4),
(4, 5)
)).toDF("src", "dst")
val g = GraphFrame.fromEdges(edgesDf)
g.bfs.fromExpr("id = 1").toExpr("id <> 1").run().show()
+----+-----+---+
|from| e0| to|
+----+-----+---+
| [1]|[1,2]|[2]|
+----+-----+---+
假设您这样查询它:
g.bfs.fromExpr("id = 1").toExpr("id > 3").run().show()
+----+-----+---+-----+---+-----+---+
|from| e0| v1| e1| v2| e2| to|
+----+-----+---+-----+---+-----+---+
| [1]|[1,2]|[2]|[2,3]|[3]|[3,4]|[4]|
+----+-----+---+-----+---+-----+---+
现在bfs
方法需要三个跃点。这是从1到大于3的节点的最短路径。即使存在从4到5(和5> 3)的边缘,它也不会继续,因为这将是更长的路径(四跳)。
另一个问题:GraphFrames是针对性的,不是吗?为了获得“非直接图”,我应该添加倒数边,不应该吗?
我认为这取决于您要应用于图表的算法。有人可能会编写一个忽略底层edges
DataFrame方向的算法。但是如果算法假定有向图,那么我认为你是对的:你必须添加相互的边。
如果您将此问题作为一个单独的问题,您可能会得到更好的回复(来自其他人)。