Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/readwrite/edgelist.py: 18%
78 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""
2**********
3Edge Lists
4**********
5Read and write NetworkX graphs as edge lists.
7The multi-line adjacency list format is useful for graphs with nodes
8that can be meaningfully represented as strings. With the edgelist
9format simple edge data can be stored but node or graph data is not.
10There is no way of representing isolated nodes unless the node has a
11self-loop edge.
13Format
14------
15You can read or write three formats of edge lists with these functions.
17Node pairs with no data::
19 1 2
21Python dictionary as data::
23 1 2 {'weight':7, 'color':'green'}
25Arbitrary data::
27 1 2 7 green
28"""
30__all__ = [
31 "generate_edgelist",
32 "write_edgelist",
33 "parse_edgelist",
34 "read_edgelist",
35 "read_weighted_edgelist",
36 "write_weighted_edgelist",
37]
39import networkx as nx
40from networkx.utils import open_file
43def generate_edgelist(G, delimiter=" ", data=True):
44 """Generate a single line of the graph G in edge list format.
46 Parameters
47 ----------
48 G : NetworkX graph
50 delimiter : string, optional
51 Separator for node labels
53 data : bool or list of keys
54 If False generate no edge data. If True use a dictionary
55 representation of edge data. If a list of keys use a list of data
56 values corresponding to the keys.
58 Returns
59 -------
60 lines : string
61 Lines of data in adjlist format.
63 Examples
64 --------
65 >>> G = nx.lollipop_graph(4, 3)
66 >>> G[1][2]["weight"] = 3
67 >>> G[3][4]["capacity"] = 12
68 >>> for line in nx.generate_edgelist(G, data=False):
69 ... print(line)
70 0 1
71 0 2
72 0 3
73 1 2
74 1 3
75 2 3
76 3 4
77 4 5
78 5 6
80 >>> for line in nx.generate_edgelist(G):
81 ... print(line)
82 0 1 {}
83 0 2 {}
84 0 3 {}
85 1 2 {'weight': 3}
86 1 3 {}
87 2 3 {}
88 3 4 {'capacity': 12}
89 4 5 {}
90 5 6 {}
92 >>> for line in nx.generate_edgelist(G, data=["weight"]):
93 ... print(line)
94 0 1
95 0 2
96 0 3
97 1 2 3
98 1 3
99 2 3
100 3 4
101 4 5
102 5 6
104 See Also
105 --------
106 write_adjlist, read_adjlist
107 """
108 if data is True:
109 for u, v, d in G.edges(data=True):
110 e = u, v, dict(d)
111 yield delimiter.join(map(str, e))
112 elif data is False:
113 for u, v in G.edges(data=False):
114 e = u, v
115 yield delimiter.join(map(str, e))
116 else:
117 for u, v, d in G.edges(data=True):
118 e = [u, v]
119 try:
120 e.extend(d[k] for k in data)
121 except KeyError:
122 pass # missing data for this edge, should warn?
123 yield delimiter.join(map(str, e))
126@open_file(1, mode="wb")
127def write_edgelist(G, path, comments="#", delimiter=" ", data=True, encoding="utf-8"):
128 """Write graph as a list of edges.
130 Parameters
131 ----------
132 G : graph
133 A NetworkX graph
134 path : file or string
135 File or filename to write. If a file is provided, it must be
136 opened in 'wb' mode. Filenames ending in .gz or .bz2 will be compressed.
137 comments : string, optional
138 The character used to indicate the start of a comment
139 delimiter : string, optional
140 The string used to separate values. The default is whitespace.
141 data : bool or list, optional
142 If False write no edge data.
143 If True write a string representation of the edge data dictionary..
144 If a list (or other iterable) is provided, write the keys specified
145 in the list.
146 encoding: string, optional
147 Specify which encoding to use when writing file.
149 Examples
150 --------
151 >>> G = nx.path_graph(4)
152 >>> nx.write_edgelist(G, "test.edgelist")
153 >>> G = nx.path_graph(4)
154 >>> fh = open("test.edgelist", "wb")
155 >>> nx.write_edgelist(G, fh)
156 >>> nx.write_edgelist(G, "test.edgelist.gz")
157 >>> nx.write_edgelist(G, "test.edgelist.gz", data=False)
159 >>> G = nx.Graph()
160 >>> G.add_edge(1, 2, weight=7, color="red")
161 >>> nx.write_edgelist(G, "test.edgelist", data=False)
162 >>> nx.write_edgelist(G, "test.edgelist", data=["color"])
163 >>> nx.write_edgelist(G, "test.edgelist", data=["color", "weight"])
165 See Also
166 --------
167 read_edgelist
168 write_weighted_edgelist
169 """
171 for line in generate_edgelist(G, delimiter, data):
172 line += "\n"
173 path.write(line.encode(encoding))
176@nx._dispatch(graphs=None)
177def parse_edgelist(
178 lines, comments="#", delimiter=None, create_using=None, nodetype=None, data=True
179):
180 """Parse lines of an edge list representation of a graph.
182 Parameters
183 ----------
184 lines : list or iterator of strings
185 Input data in edgelist format
186 comments : string, optional
187 Marker for comment lines. Default is `'#'`. To specify that no character
188 should be treated as a comment, use ``comments=None``.
189 delimiter : string, optional
190 Separator for node labels. Default is `None`, meaning any whitespace.
191 create_using : NetworkX graph constructor, optional (default=nx.Graph)
192 Graph type to create. If graph instance, then cleared before populated.
193 nodetype : Python type, optional
194 Convert nodes to this type. Default is `None`, meaning no conversion is
195 performed.
196 data : bool or list of (label,type) tuples
197 If `False` generate no edge data or if `True` use a dictionary
198 representation of edge data or a list tuples specifying dictionary
199 key names and types for edge data.
201 Returns
202 -------
203 G: NetworkX Graph
204 The graph corresponding to lines
206 Examples
207 --------
208 Edgelist with no data:
210 >>> lines = ["1 2", "2 3", "3 4"]
211 >>> G = nx.parse_edgelist(lines, nodetype=int)
212 >>> list(G)
213 [1, 2, 3, 4]
214 >>> list(G.edges())
215 [(1, 2), (2, 3), (3, 4)]
217 Edgelist with data in Python dictionary representation:
219 >>> lines = ["1 2 {'weight': 3}", "2 3 {'weight': 27}", "3 4 {'weight': 3.0}"]
220 >>> G = nx.parse_edgelist(lines, nodetype=int)
221 >>> list(G)
222 [1, 2, 3, 4]
223 >>> list(G.edges(data=True))
224 [(1, 2, {'weight': 3}), (2, 3, {'weight': 27}), (3, 4, {'weight': 3.0})]
226 Edgelist with data in a list:
228 >>> lines = ["1 2 3", "2 3 27", "3 4 3.0"]
229 >>> G = nx.parse_edgelist(lines, nodetype=int, data=(("weight", float),))
230 >>> list(G)
231 [1, 2, 3, 4]
232 >>> list(G.edges(data=True))
233 [(1, 2, {'weight': 3.0}), (2, 3, {'weight': 27.0}), (3, 4, {'weight': 3.0})]
235 See Also
236 --------
237 read_weighted_edgelist
238 """
239 from ast import literal_eval
241 G = nx.empty_graph(0, create_using)
242 for line in lines:
243 if comments is not None:
244 p = line.find(comments)
245 if p >= 0:
246 line = line[:p]
247 if not line:
248 continue
249 # split line, should have 2 or more
250 s = line.strip().split(delimiter)
251 if len(s) < 2:
252 continue
253 u = s.pop(0)
254 v = s.pop(0)
255 d = s
256 if nodetype is not None:
257 try:
258 u = nodetype(u)
259 v = nodetype(v)
260 except Exception as err:
261 raise TypeError(
262 f"Failed to convert nodes {u},{v} to type {nodetype}."
263 ) from err
265 if len(d) == 0 or data is False:
266 # no data or data type specified
267 edgedata = {}
268 elif data is True:
269 # no edge types specified
270 try: # try to evaluate as dictionary
271 if delimiter == ",":
272 edgedata_str = ",".join(d)
273 else:
274 edgedata_str = " ".join(d)
275 edgedata = dict(literal_eval(edgedata_str.strip()))
276 except Exception as err:
277 raise TypeError(
278 f"Failed to convert edge data ({d}) to dictionary."
279 ) from err
280 else:
281 # convert edge data to dictionary with specified keys and type
282 if len(d) != len(data):
283 raise IndexError(
284 f"Edge data {d} and data_keys {data} are not the same length"
285 )
286 edgedata = {}
287 for (edge_key, edge_type), edge_value in zip(data, d):
288 try:
289 edge_value = edge_type(edge_value)
290 except Exception as err:
291 raise TypeError(
292 f"Failed to convert {edge_key} data {edge_value} "
293 f"to type {edge_type}."
294 ) from err
295 edgedata.update({edge_key: edge_value})
296 G.add_edge(u, v, **edgedata)
297 return G
300@open_file(0, mode="rb")
301@nx._dispatch(graphs=None)
302def read_edgelist(
303 path,
304 comments="#",
305 delimiter=None,
306 create_using=None,
307 nodetype=None,
308 data=True,
309 edgetype=None,
310 encoding="utf-8",
311):
312 """Read a graph from a list of edges.
314 Parameters
315 ----------
316 path : file or string
317 File or filename to read. If a file is provided, it must be
318 opened in 'rb' mode.
319 Filenames ending in .gz or .bz2 will be uncompressed.
320 comments : string, optional
321 The character used to indicate the start of a comment. To specify that
322 no character should be treated as a comment, use ``comments=None``.
323 delimiter : string, optional
324 The string used to separate values. The default is whitespace.
325 create_using : NetworkX graph constructor, optional (default=nx.Graph)
326 Graph type to create. If graph instance, then cleared before populated.
327 nodetype : int, float, str, Python type, optional
328 Convert node data from strings to specified type
329 data : bool or list of (label,type) tuples
330 Tuples specifying dictionary key names and types for edge data
331 edgetype : int, float, str, Python type, optional OBSOLETE
332 Convert edge data from strings to specified type and use as 'weight'
333 encoding: string, optional
334 Specify which encoding to use when reading file.
336 Returns
337 -------
338 G : graph
339 A networkx Graph or other type specified with create_using
341 Examples
342 --------
343 >>> nx.write_edgelist(nx.path_graph(4), "test.edgelist")
344 >>> G = nx.read_edgelist("test.edgelist")
346 >>> fh = open("test.edgelist", "rb")
347 >>> G = nx.read_edgelist(fh)
348 >>> fh.close()
350 >>> G = nx.read_edgelist("test.edgelist", nodetype=int)
351 >>> G = nx.read_edgelist("test.edgelist", create_using=nx.DiGraph)
353 Edgelist with data in a list:
355 >>> textline = "1 2 3"
356 >>> fh = open("test.edgelist", "w")
357 >>> d = fh.write(textline)
358 >>> fh.close()
359 >>> G = nx.read_edgelist("test.edgelist", nodetype=int, data=(("weight", float),))
360 >>> list(G)
361 [1, 2]
362 >>> list(G.edges(data=True))
363 [(1, 2, {'weight': 3.0})]
365 See parse_edgelist() for more examples of formatting.
367 See Also
368 --------
369 parse_edgelist
370 write_edgelist
372 Notes
373 -----
374 Since nodes must be hashable, the function nodetype must return hashable
375 types (e.g. int, float, str, frozenset - or tuples of those, etc.)
376 """
377 lines = (line if isinstance(line, str) else line.decode(encoding) for line in path)
378 return parse_edgelist(
379 lines,
380 comments=comments,
381 delimiter=delimiter,
382 create_using=create_using,
383 nodetype=nodetype,
384 data=data,
385 )
388def write_weighted_edgelist(G, path, comments="#", delimiter=" ", encoding="utf-8"):
389 """Write graph G as a list of edges with numeric weights.
391 Parameters
392 ----------
393 G : graph
394 A NetworkX graph
395 path : file or string
396 File or filename to write. If a file is provided, it must be
397 opened in 'wb' mode.
398 Filenames ending in .gz or .bz2 will be compressed.
399 comments : string, optional
400 The character used to indicate the start of a comment
401 delimiter : string, optional
402 The string used to separate values. The default is whitespace.
403 encoding: string, optional
404 Specify which encoding to use when writing file.
406 Examples
407 --------
408 >>> G = nx.Graph()
409 >>> G.add_edge(1, 2, weight=7)
410 >>> nx.write_weighted_edgelist(G, "test.weighted.edgelist")
412 See Also
413 --------
414 read_edgelist
415 write_edgelist
416 read_weighted_edgelist
417 """
418 write_edgelist(
419 G,
420 path,
421 comments=comments,
422 delimiter=delimiter,
423 data=("weight",),
424 encoding=encoding,
425 )
428@nx._dispatch(graphs=None)
429def read_weighted_edgelist(
430 path,
431 comments="#",
432 delimiter=None,
433 create_using=None,
434 nodetype=None,
435 encoding="utf-8",
436):
437 """Read a graph as list of edges with numeric weights.
439 Parameters
440 ----------
441 path : file or string
442 File or filename to read. If a file is provided, it must be
443 opened in 'rb' mode.
444 Filenames ending in .gz or .bz2 will be uncompressed.
445 comments : string, optional
446 The character used to indicate the start of a comment.
447 delimiter : string, optional
448 The string used to separate values. The default is whitespace.
449 create_using : NetworkX graph constructor, optional (default=nx.Graph)
450 Graph type to create. If graph instance, then cleared before populated.
451 nodetype : int, float, str, Python type, optional
452 Convert node data from strings to specified type
453 encoding: string, optional
454 Specify which encoding to use when reading file.
456 Returns
457 -------
458 G : graph
459 A networkx Graph or other type specified with create_using
461 Notes
462 -----
463 Since nodes must be hashable, the function nodetype must return hashable
464 types (e.g. int, float, str, frozenset - or tuples of those, etc.)
466 Example edgelist file format.
468 With numeric edge data::
470 # read with
471 # >>> G=nx.read_weighted_edgelist(fh)
472 # source target data
473 a b 1
474 a c 3.14159
475 d e 42
477 See Also
478 --------
479 write_weighted_edgelist
480 """
481 return read_edgelist(
482 path,
483 comments=comments,
484 delimiter=delimiter,
485 create_using=create_using,
486 nodetype=nodetype,
487 data=(("weight", float),),
488 encoding=encoding,
489 )