"""
**********
边列表
**********
读取和写入NetworkX图作为边列表。
多行邻接列表格式对于节点可以有意义地表示为字符串的图非常有用。使用边列表格式可以存储简单的边数据,但不能存储节点或图数据。除非节点有自环边,否则无法表示孤立节点。
Format
------
您可以使用这些函数读取或写入三种格式的边列表。
无数据的节点对::
1 2
作为数据的Python字典::
1 2 {'weight':7, 'color':'green'}
任意数据::
1 2 7 green
"""
__all__ = [
"generate_edgelist",
"write_edgelist",
"parse_edgelist",
"read_edgelist",
"read_weighted_edgelist",
"write_weighted_edgelist",
]
import networkx as nx
from networkx.utils import open_file
[docs]
def generate_edgelist(G, delimiter=" ", data=True):
"""生成图 G 的单行边列表格式。
Parameters
----------
G : NetworkX 图
delimiter : 字符串, 可选
节点标签的分隔符
data : 布尔值或键列表
如果为 False,不生成边数据。如果为 True,使用边数据的字典表示。如果为键列表,使用与键对应的数据值列表。
Returns
-------
lines : 字符串
邻接表格式的数据行。
Examples
--------
>>> G = nx.lollipop_graph(4, 3)
>>> G[1][2]["weight"] = 3
>>> G[3][4]["capacity"] = 12
>>> for line in nx.generate_edgelist(G, data=False):
... print(line)
0 1
0 2
0 3
1 2
1 3
2 3
3 4
4 5
5 6
>>> for line in nx.generate_edgelist(G):
... print(line)
0 1 {}
0 2 {}
0 3 {}
1 2 {'weight': 3}
1 3 {}
2 3 {}
3 4 {'capacity': 12}
4 5 {}
5 6 {}
>>> for line in nx.generate_edgelist(G, data=["weight"]):
... print(line)
0 1
0 2
0 3
1 2 3
1 3
2 3
3 4
4 5
5 6
See Also
--------
write_adjlist, read_adjlist
"""
if data is True:
for u, v, d in G.edges(data=True):
e = u, v, dict(d)
yield delimiter.join(map(str, e))
elif data is False:
for u, v in G.edges(data=False):
e = u, v
yield delimiter.join(map(str, e))
else:
for u, v, d in G.edges(data=True):
e = [u, v]
try:
e.extend(d[k] for k in data)
except KeyError:
pass # missing data for this edge, should warn?
yield delimiter.join(map(str, e))
[docs]
@open_file(1, mode="wb")
def write_edgelist(G, path, comments="#", delimiter=" ", data=True, encoding="utf-8"):
"""将图作为边列表写入。
Parameters
----------
G : 图
一个 NetworkX 图
path : 文件或字符串
要写入的文件或文件名。如果提供文件,它必须以 'wb' 模式打开。以 .gz 或 .bz2 结尾的文件名将被压缩。
comments : 字符串, 可选
用于指示注释开始的字符
delimiter : 字符串, 可选
用于分隔值的字符串。默认是空白字符。
data : 布尔值或列表, 可选
如果为 False,不写入边数据。
如果为 True,写入边数据字典的字符串表示。
如果提供列表(或其他可迭代对象),写入列表中指定的键。
encoding: 字符串, 可选
指定写入文件时使用的编码。
Examples
--------
>>> G = nx.path_graph(4)
>>> nx.write_edgelist(G, "test.edgelist")
>>> G = nx.path_graph(4)
>>> fh = open("test.edgelist", "wb")
>>> nx.write_edgelist(G, fh)
>>> nx.write_edgelist(G, "test.edgelist.gz")
>>> nx.write_edgelist(G, "test.edgelist.gz", data=False)
>>> G = nx.Graph()
>>> G.add_edge(1, 2, weight=7, color="red")
>>> nx.write_edgelist(G, "test.edgelist", data=False)
>>> nx.write_edgelist(G, "test.edgelist", data=["color"])
>>> nx.write_edgelist(G, "test.edgelist", data=["color", "weight"])
See Also
--------
read_edgelist
write_weighted_edgelist
"""
for line in generate_edgelist(G, delimiter, data):
line += "\n"
path.write(line.encode(encoding))
[docs]
@nx._dispatchable(graphs=None, returns_graph=True)
def parse_edgelist(
lines, comments="#", delimiter=None, create_using=None, nodetype=None, data=True
):
"""解析图的边列表表示形式的行。
Parameters
----------
lines : 字符串列表或迭代器
输入数据,格式为边列表
comments : 字符串, 可选
注释行的标记。默认是 `'#'` 。要指定没有字符被视为注释,使用 ``comments=None`` 。
delimiter : 字符串, 可选
节点标签的分隔符。默认是 `None` ,表示任何空白字符。
create_using : NetworkX 图构造函数, 可选 (默认=nx.Graph)
要创建的图类型。如果是图实例,则在填充前清空。
nodetype : Python 类型, 可选
将节点转换为此类型。默认是 `None` ,表示不进行转换。
data : 布尔值或 (标签,类型) 元组列表
如果为 `False` ,则不生成边数据;如果为 `True` ,则使用字典表示的边数据或指定字典键名和类型的元组列表。
Returns
-------
G: NetworkX 图
对应于输入行的图
Examples
--------
无数据的边列表:
>>> lines = ["1 2", "2 3", "3 4"]
>>> G = nx.parse_edgelist(lines, nodetype=int)
>>> list(G)
[1, 2, 3, 4]
>>> list(G.edges())
[(1, 2), (2, 3), (3, 4)]
使用字典表示的边列表数据:
>>> lines = ["1 2 {'weight': 3}", "2 3 {'weight': 27}", "3 4 {'weight': 3.0}"]
>>> G = nx.parse_edgelist(lines, nodetype=int)
>>> list(G)
[1, 2, 3, 4]
>>> list(G.edges(data=True))
[(1, 2, {'weight': 3}), (2, 3, {'weight': 27}), (3, 4, {'weight': 3.0})]
使用列表表示的边列表数据:
>>> lines = ["1 2 3", "2 3 27", "3 4 3.0"]
>>> G = nx.parse_edgelist(lines, nodetype=int, data=(("weight", float),))
>>> list(G)
[1, 2, 3, 4]
>>> list(G.edges(data=True))
[(1, 2, {'weight': 3.0}), (2, 3, {'weight': 27.0}), (3, 4, {'weight': 3.0})]
See Also
--------
read_weighted_edgelist
"""
from ast import literal_eval
G = nx.empty_graph(0, create_using)
for line in lines:
if comments is not None:
p = line.find(comments)
if p >= 0:
line = line[:p]
if not line:
continue
# split line, should have 2 or more
s = line.rstrip("\n").split(delimiter)
if len(s) < 2:
continue
u = s.pop(0)
v = s.pop(0)
d = s
if nodetype is not None:
try:
u = nodetype(u)
v = nodetype(v)
except Exception as err:
raise TypeError(
f"Failed to convert nodes {u},{v} to type {nodetype}."
) from err
if len(d) == 0 or data is False:
# no data or data type specified
edgedata = {}
elif data is True:
# no edge types specified
try: # try to evaluate as dictionary
if delimiter == ",":
edgedata_str = ",".join(d)
else:
edgedata_str = " ".join(d)
edgedata = dict(literal_eval(edgedata_str.strip()))
except Exception as err:
raise TypeError(
f"Failed to convert edge data ({d}) to dictionary."
) from err
else:
# convert edge data to dictionary with specified keys and type
if len(d) != len(data):
raise IndexError(
f"Edge data {d} and data_keys {data} are not the same length"
)
edgedata = {}
for (edge_key, edge_type), edge_value in zip(data, d):
try:
edge_value = edge_type(edge_value)
except Exception as err:
raise TypeError(
f"Failed to convert {edge_key} data {edge_value} "
f"to type {edge_type}."
) from err
edgedata.update({edge_key: edge_value})
G.add_edge(u, v, **edgedata)
return G
[docs]
@open_file(0, mode="rb")
@nx._dispatchable(graphs=None, returns_graph=True)
def read_edgelist(
path,
comments="#",
delimiter=None,
create_using=None,
nodetype=None,
data=True,
edgetype=None,
encoding="utf-8",
):
"""从边列表读取图数据。
Parameters
----------
path : 文件或字符串
要读取的文件或文件名。如果提供的是文件,则必须以'rb'模式打开。
以.gz或.bz2结尾的文件名将被解压缩。
comments : 字符串, 可选
用于指示注释开始的字符。若不希望任何字符被视为注释,请使用 ``comments=None`` 。
delimiter : 字符串, 可选
用于分隔值的字符串。默认是空白字符。
create_using : NetworkX图构造函数, 可选 (默认=nx.Graph)
要创建的图类型。如果是图实例,则在填充前清空。
nodetype : int, float, str, Python类型, 可选
将节点数据从字符串转换为指定类型
data : bool 或 列表 of (标签,类型) 元组
指定边数据字典键名和类型的元组
edgetype : int, float, str, Python类型, 可选 (已废弃)
将边数据从字符串转换为指定类型并作为'weight'使用
encoding: 字符串, 可选
指定读取文件时使用的编码。
Returns
-------
G : 图
一个NetworkX图或其他由create_using指定的类型
Examples
--------
>>> nx.write_edgelist(nx.path_graph(4), "test.edgelist")
>>> G = nx.read_edgelist("test.edgelist")
>>> fh = open("test.edgelist", "rb")
>>> G = nx.read_edgelist(fh)
>>> fh.close()
>>> G = nx.read_edgelist("test.edgelist", nodetype=int)
>>> G = nx.read_edgelist("test.edgelist", create_using=nx.DiGraph)
包含数据的边列表示例:
>>> textline = "1 2 3"
>>> fh = open("test.edgelist", "w")
>>> d = fh.write(textline)
>>> fh.close()
>>> G = nx.read_edgelist("test.edgelist", nodetype=int, data=(("weight", float),))
>>> list(G)
[1, 2]
>>> list(G.edges(data=True))
[(1, 2, {'weight': 3.0})]
更多格式示例请参见parse_edgelist()。
See Also
--------
parse_edgelist
write_edgelist
Notes
-----
由于节点必须是可哈希的,nodetype函数必须返回可哈希的类型(例如int、float、str、frozenset或这些类型的元组等)。
"""
lines = (line if isinstance(line, str) else line.decode(encoding) for line in path)
return parse_edgelist(
lines,
comments=comments,
delimiter=delimiter,
create_using=create_using,
nodetype=nodetype,
data=data,
)
[docs]
def write_weighted_edgelist(G, path, comments="#", delimiter=" ", encoding="utf-8"):
"""将图 G 以带有数值权重的边列表形式写入。
Parameters
----------
G : 图
一个 NetworkX 图
path : 文件或字符串
要写入的文件或文件名。如果提供的是文件,则必须以 'wb' 模式打开。
以 .gz 或 .bz2 结尾的文件名将被压缩。
comments : 字符串, 可选
用于指示注释开始的字符
delimiter : 字符串, 可选
用于分隔值的字符串。默认是空白字符。
encoding: 字符串, 可选
指定写入文件时使用的编码。
Examples
--------
>>> G = nx.Graph()
>>> G.add_edge(1, 2, weight=7)
>>> nx.write_weighted_edgelist(G, "test.weighted.edgelist")
See Also
--------
read_edgelist
write_edgelist
read_weighted_edgelist
"""
write_edgelist(
G,
path,
comments=comments,
delimiter=delimiter,
data=("weight",),
encoding=encoding,
)
[docs]
@nx._dispatchable(graphs=None, returns_graph=True)
def read_weighted_edgelist(
path,
comments="#",
delimiter=None,
create_using=None,
nodetype=None,
encoding="utf-8",
):
"""读取带有数值权重的边列表形式的图。
Parameters
----------
path : 文件或字符串
要读取的文件或文件名。如果提供的是文件,必须以'rb'模式打开。
以.gz或.bz2结尾的文件名将被解压缩。
comments : 字符串, 可选
用于指示注释开始的字符。
delimiter : 字符串, 可选
用于分隔值的字符串。默认是空白字符。
create_using : NetworkX图构造函数, 可选 (默认=nx.Graph)
要创建的图类型。如果是图实例,则在填充前清空。
nodetype : int, float, str, Python类型, 可选
将节点数据从字符串转换为指定类型
encoding: 字符串, 可选
指定读取文件时使用的编码。
Returns
-------
G : 图
一个networkx图或其他由create_using指定的类型
Notes
-----
由于节点必须是可哈希的,nodetype函数必须返回可哈希的类型(例如int, float, str, frozenset - 或这些类型的元组等)
示例边列表文件格式。
带有数值边数据::
# 读取方式
# >>> G=nx.read_weighted_edgelist(fh)
# 源 目标 数据
a b 1
a c 3.14159
d e 42
See Also
--------
write_weighted_edgelist
"""
return read_edgelist(
path,
comments=comments,
delimiter=delimiter,
create_using=create_using,
nodetype=nodetype,
data=(("weight", float),),
encoding=encoding,
)