Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 使用图形工具读取Pajek.net文件_Python 3.x_Graph Tool - Fatal编程技术网

Python 3.x 使用图形工具读取Pajek.net文件

Python 3.x 使用图形工具读取Pajek.net文件,python-3.x,graph-tool,Python 3.x,Graph Tool,我有一个(带加权边的无向网络),这里提供了一个示例: *Vertices 5 1 apple 2 cat 3 tree 4 nature 5 fire *Edges 1 3 14 2 4 1 提供的节点标签不带引号。边指定为节点1、节点2、边权重 我需要将此文件作为一个无向图读取,其中包含节点标签和边的“权重”属性。该函数还应保留隔离节点 在Python中有没有一种有效的方法来实现这一点? 到目前为止,我一直在使用Networkx读取.net文件,然后使用转换函数。我正在寻找

我有一个(带加权边的无向网络),这里提供了一个示例:

*Vertices 5
1  apple
2  cat
3  tree
4  nature
5  fire
*Edges
1  3  14
2  4  1
提供的节点标签不带引号。边指定为节点1、节点2、边权重

我需要将此文件作为一个无向图读取,其中包含节点标签和边的“权重”属性。该函数还应保留隔离节点

在Python中有没有一种有效的方法来实现这一点?
到目前为止,我一直在使用Networkx读取.net文件,然后使用转换函数。我正在寻找一种加速过程的方法。

这是我今天开发的解决方案:

import graph_tool.all as gt
import graph_tool.stats as gts

def pajTOgt(filepath, directed = False, removeloops = True):
  if directed:
    g = gt.Graph(directed=True)
  else:
    g = gt.Graph(directed=False)

  #define edge and vertex properties
  g.edge_properties["weight"] = g.new_edge_property("double")
  g.vertex_properties["id"] = g.new_vertex_property("string")

  with open(filepath, encoding = "utf-8") as input_data:
    #create vertices
    for line in input_data:
        g.add_vertex(int(line.replace("*Vertices ", "").strip())) #add vertices
        break

    #label vertices
    for line in input_data: #keeps going for node labels
      if not line.strip() == '*Edges' or line.strip() == '*Arcs':  
        v_id = int(line.split()[0]) - 1
        g.vertex_properties["id"][g.vertex(v_id)] = "".join(line.split()[1:])
      else:
        break

    #create weighted edges
    for line in input_data: #keeps going for edges
      linesplit = line.split()
      linesplit = [int(x) for x in linesplit[:2]] + [float(linesplit[2])]
      if linesplit[2] > 0:
        n1 = g.vertex(linesplit[0]-1)
        n2 = g.vertex(linesplit[1]-1)
        e = g.add_edge(n1, n2)
        g.edge_properties["weight"][e] = linesplit[2]

    if removeloops:
      gts.remove_self_loops(g)

    return g

不过,如果您找到更有效的方法,我还是很想知道。

似乎Pajek文件的每个部分(顶点/边)都可以解释为以空格分隔的CSV文件,这意味着您可以使用
pandas.read_CSV()
解析它。该函数比您在纯python答案中建议的逐行解析要快

此外,一次初始化边缘列表和属性列表(作为numpy数组)比在python循环中单独设置每个元素更快

我认为下面的实现应该接近最优,但我还没有对其进行基准测试

重新导入
从io导入StringIO
将numpy作为np导入
作为pd进口熊猫
将图形工具作为gt导入
def pajek_to_gt(路径,定向=False,删除循环=False):
"""
将Pajek.NET文件[1]作为graph\u tool.graph加载。
支持通过节点对指定其边的文件。
不支持通过指定其边的文件
“边缘列表”方案(即邻居列表方案)。
注:
每个图形工具将顶点重新编号,以0开头
约定(不是以1开头的Pajek约定)。
作者:斯图尔特·伯格(github.com/stuarteberg)
执照:麻省理工学院
[1]: https://gephi.org/users/supported-graph-formats/pajek-net-format/
"""
#装入RAM
打开(路径“r”)作为f:
全文=f.阅读()
如果“*edgeslist”为全文:
引发运行时错误(“不支持邻居列表格式”)
#删除注释行
全文=re.sub(r'^\s*%.*$','',全文,标志=re.MULTILINE)
#删除空行(包括通过删除注释创建的空行)
全文=re.sub(r'\n+','\n',全文)
#确保分隔符是单个空格
全文=re.sub(r'[\t]+','',全文)
num_texts=int(StringIO(全文).readline().split()[-1])
#拆分为顶点部分和边部分
#(顶点部分可能为空)
顶点文本,边文本=重新拆分(r'\*[^\n]+\n',全文)[1:]
#分析顶点(如果存在)
v_df=无
如果是文本:
v_df=pd.read_csv(StringIO(顶点文本),分隔符='',引擎='c',名称=['id','label'],标题=None)
断言(v_df['id']==np.arange(1,1+num_顶点)).all()\
该文件未列出所有顶点,或未按顺序列出它们
#解析边
e_df=pd.read_csv(StringIO(边缘_文本),分隔符=“”,引擎=“”,标题=无)
如果len(e_df.columns)==2:
e_df.columns=['v1','v2']
elif len(e_df.columns)==3:
e_df.columns=['v1','v2','weight']
其他:
引发运行时错误(“无法理解边缘列表”)
e_df[[v1',v2']]-=1
#释放一些内存
删除全文、顶点文字、边文字
#创建图形
g=gt.图(定向=定向)
g、 添加顶点(顶点数)
g、 添加边列表(e_df['v1','v2']]值)
#添加属性
如果e_df.列中的“重量”:
g、 边缘属性[“权重”]=g.新的边缘属性(“双”,e_df[“权重”].值)
如果v_df不是无:
g、 顶点属性[“标签”]=g.新的顶点属性(“字符串”,v_df[“标签”].值)
如果删除_循环:
gt.stats.remove_self_循环(g)
返回g
下面是它为您的示例文件返回的内容:

In [1]: from pajek_to_gt import pajek_to_gt

In [2]: g = pajek_to_gt('pajek-example.NET')

In [3]: g.get_vertices()
Out[3]: array([0, 1, 2, 3, 4])

In [4]: g.vertex_properties['label'].get_2d_array([0])
Out[4]: array([['apple', 'cat', 'tree', 'nature', 'fire']], dtype='<U6')

In [5]: g.get_edges()
Out[5]:
array([[0, 2],
       [1, 3]])

In [6]: g.edge_properties['weight'].get_array()
Out[6]: PropertyArray([14.,  1.])

显然,我上面的实现与该格式不兼容。我编辑了该函数,如果文件中使用了该格式,则会引发异常。

非常感谢Stuart!我用大约43000个节点的网络对它进行了测试,你的解决方案似乎比我的快了6倍:)我害怕在内存中加载所有文件,以防有非常大的网络文件。我在这行
gt.stats.remove_self_loops(g)
,所以我将它改为
gts.remove_self_loops(g)
,使用前面的导入命令
import graph_tool.stats as gts
作为分隔符,我看到文件有时使用单个空格,有时使用多个空格(2个或更多)和其他时间选项卡。但在我看来,您的函数在所有这些情况下都能正常工作?是的,预处理正则表达式应该处理多个空格或制表符。我认为错误是我的——我忘了在代码中包含导入语句!很抱歉。(现在已修复。)正如您所看到的,我使用了
导入图形工具作为gt
,而不是
图形工具。也许这就是区别。
*edgeslist
4941 386 395 451
1 3553 3586 3587 3637
2 3583
3 4930
4 88
5 13 120