折腾了我一整天,本来以为可以拿来就用的工具pygexf结果其实需要看懂他们的源码并且比较了解lxml.etree才能用得起来,WTF……
我一边为了看懂这个玩意而煞费苦心,一边心想为什么别人的行为种下的恶因之恶果会报应到我的身上,然后开始浪费时间在脑子里想了一堆什么“但行善事莫问前程”之类的,再多来这么几次我可能就要出家了……
然后就因为这个“但行善事莫问前程”之故贫尼决心把在下受的苦写出来……也许可以帮助别人解脱苦海……
一,数据处理部分
import pandas as pd
in_file_name = '<your_file_name>'
data = pd.read_csv(in_file_name, sep="\t")
用的是pandas
我也是最近才刚开始用这个东西真的超级好用的
具体的数据格式来回倒腾的细节就不多说了吧没有什么普适性
二,事先准备,定义一些gexf的基本信息,以及node的attribute之类的
from gexf import Gexf
gexf = Gexf("PatriciaXiao","the Social Influence network")
graph = gexf.addGraph("directed","static","the Social Influence network")
attr_mod_class = graph.addNodeAttribute(force_id='modularity_class', title='Modularity Class', type='string')
三,具体添加一个点的时候
# tmp_id 是 在gexf里node的id, 0, 1, 2, 3...这样
# node_id 与其说是node的id不如说是node的name
# node_dict 是我之前自己用来处理node的时候弄出来的一些信息,在此处不是重点
tmp_id = 0
for node_id in node_dict:
node_type = '<whatever type you want>'
tmp_node = graph.addNode(str(tmp_id), str(node_id))
tmp_node.addAttribute(attr_mod_class, node_type)
tmp_node_xml = tmp_node.getXML()
tmp_id += 1
四,具体添加一个边的时候
graph.addEdge(line_idx, src_id, dst_id, weight=weight)
注意 src_id, dst_id 都对应着上边的tmp_id (0, 1, 2, 3...)而不是node_id
五,(重点来了……)写入文件
如果你没有什么特殊需求,就比如你只想要看到这样的就满足了
<node id="0" label="3054465">
<attvalues>
<attvalue for="modularity_class" value="Both"/>
</attvalues>
</node>
<edge id="0" source="33" target="2" weight="0.34360769391">
</edge>
那么恭喜你已经大功告成,你可以直接使用Gexf类自带的库函数写入文件,so easy
output_file=open(out_file_name, "w")
gexf.write(output_file)
output_file.close()
但是有特殊需求的,就比如说我,我想要
<node id="0" label="3054465">
<attvalues>
<attvalue for="modularity_class" value="Both"/>
</attvalues>
<viz:size value="1.56120125382"/>
<viz:color r="96" g="70" b="50"/>
</node>
和
<edge id="0" source="33" target="2" weight="0.34360769391">
<viz:thickness value="0.34360769391"/>
<viz:color r="40" g="145" b="145"/>
</edge>
所以我还必须想办法写进去这个<viz:XXX>
这次就连谷歌娘都抛弃了我,我猜是因为这个坑爹的gexf包写得太随心所欲所以没几个人和它死磕吧……
那我还能怎么办,我也很绝望啊,我只好自己和它死磕了啊
结果还真让我找到了一个办法
也许不是最好的办法但是聊胜于无吧
首先当然是把那些对应node与edge的那些color啊thickness啊size啊存在一个dict里面一会儿好找出来
然后具体怎么写呢,就是写入的时候不用Gexf.write
自己来写
大致是像下面这样
output_file=open(out_file_name, "w")
gexf_xml = gexf.getXML()
for gexf_elem in gexf_xml:
if gexf_elem.tag == 'graph':
for gexf_nodes_links in gexf_elem:
if gexf_nodes_links.tag == 'nodes':
print "dealing with nodes viz"
for node in gexf_nodes_links:
tmp_id = node.get('id')
node_id = node_id_list[tmp_id]
node_rgb = node_rgb_list[node_id]
size_value = str(node_size_list[node_id])
size = etree.SubElement(node, '{%s}size' % gexf.viz)
size.set('value', size_value)
color = etree.SubElement(node, '{%s}color' % gexf.viz)
color.set('r', node_rgb[0])
color.set('g', node_rgb[1])
color.set('b', node_rgb[2])
elif gexf_nodes_links.tag == 'edges':
print "dealing with edges viz"
for edge in gexf_nodes_links:
src_tmp_id = edge.get('source')
dst_tmp_id = edge.get('target')
src_id = node_id_list[src_tmp_id]
dst_id = node_id_list[dst_tmp_id]
weight = str(edge_weigh_lst[(src_id, dst_id)])
thickness = etree.SubElement(edge, '{%s}thickness' % gexf.viz)
thickness.set('value', weight)
color_rgb = edge_color_lst[(src_id, dst_id)]
color = etree.SubElement(edge, '{%s}color' % gexf.viz)
color.set('r', color_rgb[0])
color.set('g', color_rgb[1])
color.set('b', color_rgb[2])
output_file.write(etree.tostring(gexf_xml, pretty_print=True, encoding='utf-8', xml_declaration=True))
output_file.close()
夜深了贫尼该就寝了
明天还要早起化缘呢
阿弥陀佛
善哉善哉
我佛慈悲
保佑最近代码不出bug看paper不出误会吧
伤不起了伤不起了