4

graphframes是一个基于 PySpark DataFrames 的网络分析工具。以下代码是教程子图示例的修改版本:

from graphframes.examples import Graphs
import graphframes
g = Graphs(sqlContext).friends()  # Get example graph
# Select subgraph of users older than 30
v2 = g.vertices.filter("age > 30")
g2 = graphframes.GraphFrame(v2, g.edges)

与原始图相比,人们会期望新图g2将包含更少的节点和更少的边g。然而,这种情况并非如此:

print(g.vertices.count(), g.edges.count())
print(g2.vertices.count(), g2.edges.count())

给出输出:

(6, 7)
(7, 4)

很明显,结果图包含不存在节点的边。更令人不安的是g.degreesg2.degrees是相同的。这意味着至少有一些图形功能忽略了节点信息。有没有一种好方法可以确保仅使用提供的参数和参数GraphFrame的交集来创建图形?nodesedges

4

3 回答 3

3

我用来对图框进行子图化的一种方法是使用图案:

motifs = g.find("(a)-[e]->(b)").filter(<conditions for a,b or e>)
new_vertices = sqlContext.createDataFrame(motifs.map(lambda row: row.a).union(motifs.map(lambda row: row.b)).distinct())
new_edges = sqlContext.createDataFrame(motifs.map(lambda row:row.e).distinct())
new_graph = GraphFrame(new_vertices,new_edges)

虽然这看起来更复杂,并且在运行时可能需要更长的时间,但对于更复杂的图查询,这很适合您作为单个实体与图框进行交互,而不是顶点和边是分开的。因此,对顶点进行过滤也会影响图框中留下的边。

于 2016-08-15T22:14:14.850 回答
2

有趣..我看不到结果:

>>> from graphframes.examples import Graphs
>>> import graphframes
>>> g = Graphs(sqlContext).friends()  # Get example graph
>>> # Select subgraph of users older than 30
... v2 = g.vertices.filter("age > 30")
>>> g2 = graphframes.GraphFrame(v2, g.edges)
>>> print(g.vertices.count(), g.edges.count())
(6, 7)
>>> print(g2.vertices.count(), g2.edges.count())
(4, 7)

GraphFrames 截至目前不检查图形是否有效 - 即。在图构建时,所有边都连接到顶点等。但似乎过滤后的顶点数是正确的?

于 2016-06-15T00:51:17.207 回答
0

我的解决方法可能不是完美的,但它们对我有用。

我得到的问题陈述:有一个过滤的节点集合filters_nodes,我们只想让原始图中的边包含来自filters_nodes的节点。

方法 1:使用连接(代价高昂)

edgesframe = graphframe.edges
src_join = edgesframe.join(filtered_nodes, (edgesframe.src == subgraph_nodes.id), "inner").withColumnRenamed("src", "srcto")
dst_join = edgesframe.join(filtered_nodes, (edgesframe.dst == subgraph_nodes.id), "inner").withColumnRenamed("dst", "dstto")
final_join = src_join.join(dst_join, (src_join.src == dst_join.src) & (src_join.dst == dst_join.dst), "inner").select("src", "dst")
g2 = GraphFrame(filtered_nodes, final_join)

方法 2:使用收集的集合作为isin方法的列表引用(我只会在过滤器节点的小集合上使用它)

edgesframe = graphframe.edges
collected_nodes = subgraph_nodes.select("columnWeUseForReference").rdd.map(lambda r: r[0]).collect()
edgs = edgesframe.filter(edgesframe.src.isin(collected_nodes) & edgesframe.dst.isin(collected_nodes))

有人有更好的方法吗?我会很高兴看到它。

于 2021-03-22T16:09:37.423 回答