Mercurial > repos > shellac > sam_consensus_v3
comparison env/lib/python3.9/site-packages/networkx/convert.py @ 0:4f3585e2f14b draft default tip
"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author | shellac |
---|---|
date | Mon, 22 Mar 2021 18:12:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4f3585e2f14b |
---|---|
1 """Functions to convert NetworkX graphs to and from other formats. | |
2 | |
3 The preferred way of converting data to a NetworkX graph is through the | |
4 graph constructor. The constructor calls the to_networkx_graph() function | |
5 which attempts to guess the input type and convert it automatically. | |
6 | |
7 Examples | |
8 -------- | |
9 Create a graph with a single edge from a dictionary of dictionaries | |
10 | |
11 >>> d = {0: {1: 1}} # dict-of-dicts single edge (0,1) | |
12 >>> G = nx.Graph(d) | |
13 | |
14 See Also | |
15 -------- | |
16 nx_agraph, nx_pydot | |
17 """ | |
18 import warnings | |
19 import networkx as nx | |
20 from collections.abc import Collection, Generator, Iterator | |
21 | |
22 __all__ = [ | |
23 "to_networkx_graph", | |
24 "from_dict_of_dicts", | |
25 "to_dict_of_dicts", | |
26 "from_dict_of_lists", | |
27 "to_dict_of_lists", | |
28 "from_edgelist", | |
29 "to_edgelist", | |
30 ] | |
31 | |
32 | |
33 def to_networkx_graph(data, create_using=None, multigraph_input=False): | |
34 """Make a NetworkX graph from a known data structure. | |
35 | |
36 The preferred way to call this is automatically | |
37 from the class constructor | |
38 | |
39 >>> d = {0: {1: {"weight": 1}}} # dict-of-dicts single edge (0,1) | |
40 >>> G = nx.Graph(d) | |
41 | |
42 instead of the equivalent | |
43 | |
44 >>> G = nx.from_dict_of_dicts(d) | |
45 | |
46 Parameters | |
47 ---------- | |
48 data : object to be converted | |
49 | |
50 Current known types are: | |
51 any NetworkX graph | |
52 dict-of-dicts | |
53 dict-of-lists | |
54 container (e.g. set, list, tuple) of edges | |
55 iterator (e.g. itertools.chain) that produces edges | |
56 generator of edges | |
57 Pandas DataFrame (row per edge) | |
58 numpy matrix | |
59 numpy ndarray | |
60 scipy sparse matrix | |
61 pygraphviz agraph | |
62 | |
63 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
64 Graph type to create. If graph instance, then cleared before populated. | |
65 | |
66 multigraph_input : bool (default False) | |
67 If True and data is a dict_of_dicts, | |
68 try to create a multigraph assuming dict_of_dict_of_lists. | |
69 If data and create_using are both multigraphs then create | |
70 a multigraph from a multigraph. | |
71 | |
72 """ | |
73 # NX graph | |
74 if hasattr(data, "adj"): | |
75 try: | |
76 result = from_dict_of_dicts( | |
77 data.adj, | |
78 create_using=create_using, | |
79 multigraph_input=data.is_multigraph(), | |
80 ) | |
81 if hasattr(data, "graph"): # data.graph should be dict-like | |
82 result.graph.update(data.graph) | |
83 if hasattr(data, "nodes"): # data.nodes should be dict-like | |
84 # result.add_node_from(data.nodes.items()) possible but | |
85 # for custom node_attr_dict_factory which may be hashable | |
86 # will be unexpected behavior | |
87 for n, dd in data.nodes.items(): | |
88 result._node[n].update(dd) | |
89 return result | |
90 except Exception as e: | |
91 raise nx.NetworkXError("Input is not a correct NetworkX graph.") from e | |
92 | |
93 # pygraphviz agraph | |
94 if hasattr(data, "is_strict"): | |
95 try: | |
96 return nx.nx_agraph.from_agraph(data, create_using=create_using) | |
97 except Exception as e: | |
98 raise nx.NetworkXError("Input is not a correct pygraphviz graph.") from e | |
99 | |
100 # dict of dicts/lists | |
101 if isinstance(data, dict): | |
102 try: | |
103 return from_dict_of_dicts( | |
104 data, create_using=create_using, multigraph_input=multigraph_input | |
105 ) | |
106 except: | |
107 try: | |
108 return from_dict_of_lists(data, create_using=create_using) | |
109 except Exception as e: | |
110 raise TypeError("Input is not known type.") from e | |
111 | |
112 # Pandas DataFrame | |
113 try: | |
114 import pandas as pd | |
115 | |
116 if isinstance(data, pd.DataFrame): | |
117 if data.shape[0] == data.shape[1]: | |
118 try: | |
119 return nx.from_pandas_adjacency(data, create_using=create_using) | |
120 except Exception as e: | |
121 msg = "Input is not a correct Pandas DataFrame adjacency matrix." | |
122 raise nx.NetworkXError(msg) from e | |
123 else: | |
124 try: | |
125 return nx.from_pandas_edgelist( | |
126 data, edge_attr=True, create_using=create_using | |
127 ) | |
128 except Exception as e: | |
129 msg = "Input is not a correct Pandas DataFrame edge-list." | |
130 raise nx.NetworkXError(msg) from e | |
131 except ImportError: | |
132 msg = "pandas not found, skipping conversion test." | |
133 warnings.warn(msg, ImportWarning) | |
134 | |
135 # numpy matrix or ndarray | |
136 try: | |
137 import numpy | |
138 | |
139 if isinstance(data, (numpy.matrix, numpy.ndarray)): | |
140 try: | |
141 return nx.from_numpy_matrix(data, create_using=create_using) | |
142 except Exception as e: | |
143 raise nx.NetworkXError( | |
144 "Input is not a correct numpy matrix or array." | |
145 ) from e | |
146 except ImportError: | |
147 warnings.warn("numpy not found, skipping conversion test.", ImportWarning) | |
148 | |
149 # scipy sparse matrix - any format | |
150 try: | |
151 import scipy | |
152 | |
153 if hasattr(data, "format"): | |
154 try: | |
155 return nx.from_scipy_sparse_matrix(data, create_using=create_using) | |
156 except Exception as e: | |
157 raise nx.NetworkXError( | |
158 "Input is not a correct scipy sparse matrix type." | |
159 ) from e | |
160 except ImportError: | |
161 warnings.warn("scipy not found, skipping conversion test.", ImportWarning) | |
162 | |
163 # Note: most general check - should remain last in order of execution | |
164 # Includes containers (e.g. list, set, dict, etc.), generators, and | |
165 # iterators (e.g. itertools.chain) of edges | |
166 | |
167 if isinstance(data, (Collection, Generator, Iterator)): | |
168 try: | |
169 return from_edgelist(data, create_using=create_using) | |
170 except Exception as e: | |
171 raise nx.NetworkXError("Input is not a valid edge list") from e | |
172 | |
173 raise nx.NetworkXError("Input is not a known data type for conversion.") | |
174 | |
175 | |
176 def to_dict_of_lists(G, nodelist=None): | |
177 """Returns adjacency representation of graph as a dictionary of lists. | |
178 | |
179 Parameters | |
180 ---------- | |
181 G : graph | |
182 A NetworkX graph | |
183 | |
184 nodelist : list | |
185 Use only nodes specified in nodelist | |
186 | |
187 Notes | |
188 ----- | |
189 Completely ignores edge data for MultiGraph and MultiDiGraph. | |
190 | |
191 """ | |
192 if nodelist is None: | |
193 nodelist = G | |
194 | |
195 d = {} | |
196 for n in nodelist: | |
197 d[n] = [nbr for nbr in G.neighbors(n) if nbr in nodelist] | |
198 return d | |
199 | |
200 | |
201 def from_dict_of_lists(d, create_using=None): | |
202 """Returns a graph from a dictionary of lists. | |
203 | |
204 Parameters | |
205 ---------- | |
206 d : dictionary of lists | |
207 A dictionary of lists adjacency representation. | |
208 | |
209 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
210 Graph type to create. If graph instance, then cleared before populated. | |
211 | |
212 Examples | |
213 -------- | |
214 >>> dol = {0: [1]} # single edge (0,1) | |
215 >>> G = nx.from_dict_of_lists(dol) | |
216 | |
217 or | |
218 | |
219 >>> G = nx.Graph(dol) # use Graph constructor | |
220 | |
221 """ | |
222 G = nx.empty_graph(0, create_using) | |
223 G.add_nodes_from(d) | |
224 if G.is_multigraph() and not G.is_directed(): | |
225 # a dict_of_lists can't show multiedges. BUT for undirected graphs, | |
226 # each edge shows up twice in the dict_of_lists. | |
227 # So we need to treat this case separately. | |
228 seen = {} | |
229 for node, nbrlist in d.items(): | |
230 for nbr in nbrlist: | |
231 if nbr not in seen: | |
232 G.add_edge(node, nbr) | |
233 seen[node] = 1 # don't allow reverse edge to show up | |
234 else: | |
235 G.add_edges_from( | |
236 ((node, nbr) for node, nbrlist in d.items() for nbr in nbrlist) | |
237 ) | |
238 return G | |
239 | |
240 | |
241 def to_dict_of_dicts(G, nodelist=None, edge_data=None): | |
242 """Returns adjacency representation of graph as a dictionary of dictionaries. | |
243 | |
244 Parameters | |
245 ---------- | |
246 G : graph | |
247 A NetworkX graph | |
248 | |
249 nodelist : list | |
250 Use only nodes specified in nodelist | |
251 | |
252 edge_data : list, optional | |
253 If provided, the value of the dictionary will be | |
254 set to edge_data for all edges. This is useful to make | |
255 an adjacency matrix type representation with 1 as the edge data. | |
256 If edgedata is None, the edgedata in G is used to fill the values. | |
257 If G is a multigraph, the edgedata is a dict for each pair (u,v). | |
258 """ | |
259 dod = {} | |
260 if nodelist is None: | |
261 if edge_data is None: | |
262 for u, nbrdict in G.adjacency(): | |
263 dod[u] = nbrdict.copy() | |
264 else: # edge_data is not None | |
265 for u, nbrdict in G.adjacency(): | |
266 dod[u] = dod.fromkeys(nbrdict, edge_data) | |
267 else: # nodelist is not None | |
268 if edge_data is None: | |
269 for u in nodelist: | |
270 dod[u] = {} | |
271 for v, data in ((v, data) for v, data in G[u].items() if v in nodelist): | |
272 dod[u][v] = data | |
273 else: # nodelist and edge_data are not None | |
274 for u in nodelist: | |
275 dod[u] = {} | |
276 for v in (v for v in G[u] if v in nodelist): | |
277 dod[u][v] = edge_data | |
278 return dod | |
279 | |
280 | |
281 def from_dict_of_dicts(d, create_using=None, multigraph_input=False): | |
282 """Returns a graph from a dictionary of dictionaries. | |
283 | |
284 Parameters | |
285 ---------- | |
286 d : dictionary of dictionaries | |
287 A dictionary of dictionaries adjacency representation. | |
288 | |
289 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
290 Graph type to create. If graph instance, then cleared before populated. | |
291 | |
292 multigraph_input : bool (default False) | |
293 When True, the values of the inner dict are assumed | |
294 to be containers of edge data for multiple edges. | |
295 Otherwise this routine assumes the edge data are singletons. | |
296 | |
297 Examples | |
298 -------- | |
299 >>> dod = {0: {1: {"weight": 1}}} # single edge (0,1) | |
300 >>> G = nx.from_dict_of_dicts(dod) | |
301 | |
302 or | |
303 | |
304 >>> G = nx.Graph(dod) # use Graph constructor | |
305 | |
306 """ | |
307 G = nx.empty_graph(0, create_using) | |
308 G.add_nodes_from(d) | |
309 # is dict a MultiGraph or MultiDiGraph? | |
310 if multigraph_input: | |
311 # make a copy of the list of edge data (but not the edge data) | |
312 if G.is_directed(): | |
313 if G.is_multigraph(): | |
314 G.add_edges_from( | |
315 (u, v, key, data) | |
316 for u, nbrs in d.items() | |
317 for v, datadict in nbrs.items() | |
318 for key, data in datadict.items() | |
319 ) | |
320 else: | |
321 G.add_edges_from( | |
322 (u, v, data) | |
323 for u, nbrs in d.items() | |
324 for v, datadict in nbrs.items() | |
325 for key, data in datadict.items() | |
326 ) | |
327 else: # Undirected | |
328 if G.is_multigraph(): | |
329 seen = set() # don't add both directions of undirected graph | |
330 for u, nbrs in d.items(): | |
331 for v, datadict in nbrs.items(): | |
332 if (u, v) not in seen: | |
333 G.add_edges_from( | |
334 (u, v, key, data) for key, data in datadict.items() | |
335 ) | |
336 seen.add((v, u)) | |
337 else: | |
338 seen = set() # don't add both directions of undirected graph | |
339 for u, nbrs in d.items(): | |
340 for v, datadict in nbrs.items(): | |
341 if (u, v) not in seen: | |
342 G.add_edges_from( | |
343 (u, v, data) for key, data in datadict.items() | |
344 ) | |
345 seen.add((v, u)) | |
346 | |
347 else: # not a multigraph to multigraph transfer | |
348 if G.is_multigraph() and not G.is_directed(): | |
349 # d can have both representations u-v, v-u in dict. Only add one. | |
350 # We don't need this check for digraphs since we add both directions, | |
351 # or for Graph() since it is done implicitly (parallel edges not allowed) | |
352 seen = set() | |
353 for u, nbrs in d.items(): | |
354 for v, data in nbrs.items(): | |
355 if (u, v) not in seen: | |
356 G.add_edge(u, v, key=0) | |
357 G[u][v][0].update(data) | |
358 seen.add((v, u)) | |
359 else: | |
360 G.add_edges_from( | |
361 ((u, v, data) for u, nbrs in d.items() for v, data in nbrs.items()) | |
362 ) | |
363 return G | |
364 | |
365 | |
366 def to_edgelist(G, nodelist=None): | |
367 """Returns a list of edges in the graph. | |
368 | |
369 Parameters | |
370 ---------- | |
371 G : graph | |
372 A NetworkX graph | |
373 | |
374 nodelist : list | |
375 Use only nodes specified in nodelist | |
376 | |
377 """ | |
378 if nodelist is None: | |
379 return G.edges(data=True) | |
380 return G.edges(nodelist, data=True) | |
381 | |
382 | |
383 def from_edgelist(edgelist, create_using=None): | |
384 """Returns a graph from a list of edges. | |
385 | |
386 Parameters | |
387 ---------- | |
388 edgelist : list or iterator | |
389 Edge tuples | |
390 | |
391 create_using : NetworkX graph constructor, optional (default=nx.Graph) | |
392 Graph type to create. If graph instance, then cleared before populated. | |
393 | |
394 Examples | |
395 -------- | |
396 >>> edgelist = [(0, 1)] # single edge (0,1) | |
397 >>> G = nx.from_edgelist(edgelist) | |
398 | |
399 or | |
400 | |
401 >>> G = nx.Graph(edgelist) # use Graph constructor | |
402 | |
403 """ | |
404 G = nx.empty_graph(0, create_using) | |
405 G.add_edges_from(edgelist) | |
406 return G |