最近在做一个Project,跟微博啥的有关,肉壳的工作就是给微博用户打分,看谁最重要,基本上就是简单的修改了一下Page Rank算法和HITS算法。不过第一步就是要把搭档给我的数据读出来。因为都是用户关系用网络表示,为了方便处理,前期操作都是把数据写在GraphML格式文件中。GraphML也是一种标记语言,跟HTML,XML什么的差不多,里面都是一些标签。有兴趣的话,大家自己Google一下就可以了……
搭档们用的都是R和Python,里面有包可以直接读GraphML,但是木讷的我不会用R和Python,只能在Java里找相关的包,结果还真找到一个叫Jung的包。这个包功能非常强大,可以对GraphML增删改查,还可以计算网络的PR,HITS什么的,可谓非常强大……不过今天就讲一些简单的,就是如何将GraphML文件中的数据读出来,就是这么简单……
首先,我们看一下GraphML的文件格式,
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"> <key id="d0" for="node" attr.name="color" attr.type="string"> <default>yellow</default> </key> <key id="d1" for="edge" attr.name="weight" attr.type="double"> <default>0.0</default> </key> <graph id="G" edgedefault="directed"> <node id="n0"> <data key="d0">green</data> </node> <node id="n1"/> <node id="n2"> <data key="d0">blue</data> </node> <node id="n3"> <data key="d0">red</data> </node> <node id="n4"/> <node id="n5"> <data key="d0">turquoise</data> </node> <edge id="e0" source="n0" target="n2"> <data key="d1">1.0</data> </edge> <edge id="e1" source="n0" target="n1"> <data key="d1">1.0</data> </edge> <edge id="e2" source="n1" target="n3"> <data key="d1">2.0</data> </edge> <edge id="e3" source="n3" target="n2"/> <edge id="e4" source="n2" target="n4"/> <edge id="e5" source="n3" target="n5"/> <edge id="e6" source="n5" target="n4"> <data key="d1">1.1</data> </edge> </graph> </graphml>
首先,key标签定义了Vertex和Edge的meta信息,以便以后获取到这些信息后将他们读出来。<graph id=”G” edgedefault=”directed”>定义里这个图是个有向图,不过我代码里用的是个无向图(undirected),大家使用的时候需要注意一下。之后运行一下下面的代码就好了。
GraphMLReader<undirectedgraph, Node, Edge> gmlr = new GraphMLReader<undirectedgraph, Node, Edge>(new VertexFactory(), new EdgeFactory()); //创建一个GrahpML的Reader
final UndirectedGraph graph = new UndirectedSparseMultigraph();
gmlr.load(filename, graph); //读取graph,并将内容写进graph对象
BidiMap vertex_ids = gmlr.getVertexIDs(); //获取Vertex的id
<Map> edge_meta = gmlr.getEdgeMetadata(); //获取Edge的内容
//graph对象此时只有Vertex和边的连接关系,我们需要把Vertex和Edge的附加信息写进去
for (Node n : graph.getVertices()) {
n.setUserID(vertex_ids.get(n));
n.setPageRank(0.2);
n.setAuth(1);
n.setHub(1);
}
for (Edge e : graph.getEdges()) {
e.setCapacity(Double.parseDouble(edge_meta.get("d1").transformer.transform(e))); //读取的d2信息是在GraphML文件里定义的
}
经过这么一番简单操作,graph对象就已经包含了各个Vertex和Edge的关系了……就是这么简单……Vertex和Edge对象是自己写的,下面再贴个NodeFactory和EdgeFactory的代码。
class VertexFactory implements Factory {
private int n = 0;
public Node create() {
return (new Node(n++));
}
}
class EdgeFactory implements Factory {
private int e = 0;
public Edge create() {
return (new Edge(e++));
}
}
需要注意的时候,无向图读取以后,不知道是不是因为我不会用,每条Edge的from和target读不出来,用有向图就能读出来,好奇怪……不过大家到也不用担心,因为graph有个方法叫getEndpoints,可以获取到特定边的两个顶点,然后再操作就可以了……
另外,最近在研究GitHub,虽然早就注册了,但是一直没用过……现在想想,太狗了……