图的变换操作#
我们将介绍一系列可以在图上进行新增/投影的方法,以及如何将一个复杂的图转换为可以适配普通算法应用的方法。 最后,我们展示如何将算法得到的结果加回到图中去。
具体而言,图 Graph
提供了两个增加标签的函数, 和一个投影的函数。
def add_vertices(self, vertices, label="_", properties=[], vid_field=0):
pass
def add_edges(self, edges, label="_", properties=[], src_label=None, dst_label=None, src_field=0, dst_field=1):
pass
def project(self, vertices, edges):
pass
其中,我们已经在 载图 一节见到过 add_vertices 和 add_edges 这两个函数,当时我们用它来构建一张图。 进一步的,当图构建好并载入了 Vineyard 中之后,我们仍然可以用其增加更多的标签。当然这一步并不会在原图上修改,而是会返回基于原图之上, 增加了新的标签的新图。
添加新的标签#
以 LDBC-SNB 属性图为例,我们现在载入其中一部分标签,作为接下来一系列转换操作的起始图。
import graphscope
from pathlib import Path
from graphscope.framework.loader import Loader
sess = graphscope.session()
graph = sess.g(directed=directed)
graph = graph.add_vertices(Loader("person_0_0.csv", delimiter="|"), "person")
graph = graph.add_edges(Loader("person_knows_person_0_0.csv", delimiter="|"),
"knows", src_label="person", dst_label="person"
)
# graph has 1 vertex label "person"
print(graph.schema)
到这里, 我们已经载入了一张图。接下来我们在这张图上再添加几个标签。
graph1 = graph.add_vertices(Loader("comment_0_0.csv", delimiter="|"), "comment")
# Now graph1 has 2 vertex labels "person" and "comment"
print(graph1.schema)
graph2 = graph1.add_edges(Loader("comment_replyOf_comment_0_0.csv", delimiter="|"),
"replyOf", src_label="comment", dst_label="comment"
)
# graph2 has 2 edge labels "knows" and "replyOf"
print(graph2.schema)
可以看到每次 add 都会产生一张新的图,在底层,他们共有的部分会指向同一块内存,所以并不会将原图的数据复制一份。
投影#
在某些场景下,我们需要将从一张复杂的图提取出一个子图。这个操作可以借助 project 来完成。
def project(
self,
vertices: Mapping[str, Union[List[str], None]],
edges: Union[Mapping[str, Union[List[str], None]], None]
):
pass
project 包含两个参数 vertices 和 edges,其值为一个字典,字典的键是标签名,值是要取的属性的列表。值可以为 None, 代表选择所有的属性。
project 的返回值也是一个属性图,并且可以被进一步 project。 以下是几个例子。
sub_graph = graph2.project(vertices={"person": ["firstName", "lastName"]}, edges={"knows": None})
# 包含一个点标签 "person" 和一个边标签 "knows", 以及所选择的属性。
print(sub_graph.schema)
sub_graph2 = sub_graph.project(vertices={"person": []}, edges={"knows": ["creationDate"]})
# 现在点上没有属性,边上有一个属性
print(sub_graph2.schema)
自动转换为简单图#
当执行一个仅可以跑在简单图上的算法时,其会默认将其参数中的属性图转换为简单图,如果不能进行这种转换(即多于一个点标签和一个边标签,或多于一个属性), 那么就会报错。
from graphscope import wcc
ret = wcc(sub_graph2)
# wcc(graph2) # 错误! 转换不合法,多于一个点/边标签
# wcc(sub_graph) # 错误!转换不合法,多于一个属性
将计算结果作为新的属性加入图中#
上一步算法的运行结果可以被加入一张图中, 作为点的一个属性。
不仅可以加入运算结果到直接被查询的图上,还可以将这个查询结果加到被 project 而得到被查询的图上,只要被加入属性的点标签相同。
new_graph = sub_graph2.add_column(ret, selector={'cc': 'r'})
new_graph = sub_graph.add_column(ret, selector={'cc': 'r'})
new_graph = graph.add_column(ret, selector={'cc': 'r'})