| """ |
| ********** |
| Edge Lists |
| ********** |
| Read and write NetworkX graphs as edge lists. |
| |
| The multi-line adjacency list format is useful for graphs with nodes |
| that can be meaningfully represented as strings. With the edgelist |
| format simple edge data can be stored but node or graph data is not. |
| There is no way of representing isolated nodes unless the node has a |
| self-loop edge. |
| |
| Format |
| ------ |
| You can read or write three formats of edge lists with these functions. |
| |
| Node pairs with no data:: |
| |
| 1 2 |
| |
| Python dictionary as data:: |
| |
| 1 2 {'weight':7, 'color':'green'} |
| |
| Arbitrary data:: |
| |
| 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 |
|
|
|
|
| def generate_edgelist(G, delimiter=" ", data=True): |
| """Generate a single line of the graph G in edge list format. |
| |
| Parameters |
| ---------- |
| G : NetworkX graph |
| |
| delimiter : string, optional |
| Separator for node labels |
| |
| data : bool or list of keys |
| If False generate no edge data. If True use a dictionary |
| representation of edge data. If a list of keys use a list of data |
| values corresponding to the keys. |
| |
| Returns |
| ------- |
| lines : string |
| Lines of data in adjlist format. |
| |
| 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 |
| yield delimiter.join(map(str, e)) |
|
|
|
|
| @open_file(1, mode="wb") |
| def write_edgelist(G, path, comments="#", delimiter=" ", data=True, encoding="utf-8"): |
| """Write graph as a list of edges. |
| |
| Parameters |
| ---------- |
| G : graph |
| A NetworkX graph |
| path : file or string |
| File or filename to write. If a file is provided, it must be |
| opened in 'wb' mode. Filenames ending in .gz or .bz2 will be compressed. |
| comments : string, optional |
| The character used to indicate the start of a comment |
| delimiter : string, optional |
| The string used to separate values. The default is whitespace. |
| data : bool or list, optional |
| If False write no edge data. |
| If True write a string representation of the edge data dictionary.. |
| If a list (or other iterable) is provided, write the keys specified |
| in the list. |
| encoding: string, optional |
| Specify which encoding to use when writing file. |
| |
| 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_nodata.gz", data=False) |
| |
| >>> G = nx.Graph() |
| >>> G.add_edge(1, 2, weight=7, color="red") |
| >>> nx.write_edgelist(G, "test.edgelist_bigger_nodata", data=False) |
| >>> nx.write_edgelist(G, "test.edgelist_color", data=["color"]) |
| >>> nx.write_edgelist(G, "test.edgelist_color_weight", 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)) |
|
|
|
|
| @nx._dispatchable(graphs=None, returns_graph=True) |
| def parse_edgelist( |
| lines, comments="#", delimiter=None, create_using=None, nodetype=None, data=True |
| ): |
| """Parse lines of an edge list representation of a graph. |
| |
| Parameters |
| ---------- |
| lines : list or iterator of strings |
| Input data in edgelist format |
| comments : string, optional |
| Marker for comment lines. Default is `'#'`. To specify that no character |
| should be treated as a comment, use ``comments=None``. |
| delimiter : string, optional |
| Separator for node labels. Default is `None`, meaning any whitespace. |
| create_using : NetworkX graph constructor, optional (default=nx.Graph) |
| Graph type to create. If graph instance, then cleared before populated. |
| nodetype : Python type, optional |
| Convert nodes to this type. Default is `None`, meaning no conversion is |
| performed. |
| data : bool or list of (label,type) tuples |
| If `False` generate no edge data or if `True` use a dictionary |
| representation of edge data or a list tuples specifying dictionary |
| key names and types for edge data. |
| |
| Returns |
| ------- |
| G: NetworkX Graph |
| The graph corresponding to lines |
| |
| Examples |
| -------- |
| Edgelist with no data: |
| |
| >>> 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)] |
| |
| Edgelist with data in Python dictionary representation: |
| |
| >>> 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})] |
| |
| Edgelist with data in a list: |
| |
| >>> 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 |
| |
| 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: |
| |
| edgedata = {} |
| elif data is True: |
| |
| try: |
| 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: |
| |
| 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 |
|
|
|
|
| @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", |
| ): |
| """Read a graph from a list of edges. |
| |
| Parameters |
| ---------- |
| path : file or string |
| File or filename to read. If a file is provided, it must be |
| opened in 'rb' mode. |
| Filenames ending in .gz or .bz2 will be decompressed. |
| comments : string, optional |
| The character used to indicate the start of a comment. To specify that |
| no character should be treated as a comment, use ``comments=None``. |
| delimiter : string, optional |
| The string used to separate values. The default is whitespace. |
| create_using : NetworkX graph constructor, optional (default=nx.Graph) |
| Graph type to create. If graph instance, then cleared before populated. |
| nodetype : int, float, str, Python type, optional |
| Convert node data from strings to specified type |
| data : bool or list of (label,type) tuples |
| Tuples specifying dictionary key names and types for edge data |
| edgetype : int, float, str, Python type, optional OBSOLETE |
| Convert edge data from strings to specified type and use as 'weight' |
| encoding: string, optional |
| Specify which encoding to use when reading file. |
| |
| Returns |
| ------- |
| G : graph |
| A networkx Graph or other type specified with create_using |
| |
| Examples |
| -------- |
| >>> nx.write_edgelist(nx.path_graph(4), "test.edgelist_P4") |
| >>> G = nx.read_edgelist("test.edgelist_P4") |
| |
| >>> fh = open("test.edgelist_P4", "rb") |
| >>> G = nx.read_edgelist(fh) |
| >>> fh.close() |
| |
| >>> G = nx.read_edgelist("test.edgelist_P4", nodetype=int) |
| >>> G = nx.read_edgelist("test.edgelist_P4", create_using=nx.DiGraph) |
| |
| Edgelist with data in a list: |
| |
| >>> textline = "1 2 3" |
| >>> fh = open("test.textline", "w") |
| >>> d = fh.write(textline) |
| >>> fh.close() |
| >>> G = nx.read_edgelist("test.textline", nodetype=int, data=(("weight", float),)) |
| >>> list(G) |
| [1, 2] |
| >>> list(G.edges(data=True)) |
| [(1, 2, {'weight': 3.0})] |
| |
| See parse_edgelist() for more examples of formatting. |
| |
| See Also |
| -------- |
| parse_edgelist |
| write_edgelist |
| |
| Notes |
| ----- |
| Since nodes must be hashable, the function nodetype must return hashable |
| types (e.g. int, float, str, frozenset - or tuples of those, etc.) |
| """ |
| 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, |
| ) |
|
|
|
|
| def write_weighted_edgelist(G, path, comments="#", delimiter=" ", encoding="utf-8"): |
| """Write graph G as a list of edges with numeric weights. |
| |
| Parameters |
| ---------- |
| G : graph |
| A NetworkX graph |
| path : file or string |
| File or filename to write. If a file is provided, it must be |
| opened in 'wb' mode. |
| Filenames ending in .gz or .bz2 will be compressed. |
| comments : string, optional |
| The character used to indicate the start of a comment |
| delimiter : string, optional |
| The string used to separate values. The default is whitespace. |
| encoding: string, optional |
| Specify which encoding to use when writing file. |
| |
| 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, |
| ) |
|
|
|
|
| @nx._dispatchable(graphs=None, returns_graph=True) |
| def read_weighted_edgelist( |
| path, |
| comments="#", |
| delimiter=None, |
| create_using=None, |
| nodetype=None, |
| encoding="utf-8", |
| ): |
| """Read a graph as list of edges with numeric weights. |
| |
| Parameters |
| ---------- |
| path : file or string |
| File or filename to read. If a file is provided, it must be |
| opened in 'rb' mode. |
| Filenames ending in .gz or .bz2 will be decompressed. |
| comments : string, optional |
| The character used to indicate the start of a comment. |
| delimiter : string, optional |
| The string used to separate values. The default is whitespace. |
| create_using : NetworkX graph constructor, optional (default=nx.Graph) |
| Graph type to create. If graph instance, then cleared before populated. |
| nodetype : int, float, str, Python type, optional |
| Convert node data from strings to specified type |
| encoding: string, optional |
| Specify which encoding to use when reading file. |
| |
| Returns |
| ------- |
| G : graph |
| A networkx Graph or other type specified with create_using |
| |
| Notes |
| ----- |
| Since nodes must be hashable, the function nodetype must return hashable |
| types (e.g. int, float, str, frozenset - or tuples of those, etc.) |
| |
| Example edgelist file format. |
| |
| With numeric edge data:: |
| |
| # read with |
| # >>> G=nx.read_weighted_edgelist(fh) |
| # source target data |
| 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, |
| ) |
|
|