Statistics
| Branch: | Revision:

iof-tools / networkxMiCe / networkx-master / networkx / convert.py @ 5cef0f13

History | View | Annotate | Download (13 KB)

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
#    Copyright (C) 2006-2013 by
19
#    Aric Hagberg <hagberg@lanl.gov>
20
#    Dan Schult <dschult@colgate.edu>
21
#    Pieter Swart <swart@lanl.gov>
22
#    All rights reserved.
23
#    BSD license.
24
import warnings
25
import networkx as nx
26
__author__ = """\n""".join(['Aric Hagberg <aric.hagberg@gmail.com>',
27
                            'Pieter Swart (swart@lanl.gov)',
28
                            'Dan Schult(dschult@colgate.edu)'])
29
__all__ = ['to_networkx_graph',
30
           'from_dict_of_dicts', 'to_dict_of_dicts',
31
           'from_dict_of_lists', 'to_dict_of_lists',
32
           'from_edgelist', 'to_edgelist']
33

    
34

    
35
def to_networkx_graph(data, create_using=None, multigraph_input=False):
36
    """Make a NetworkX graph from a known data structure.
37

38
    The preferred way to call this is automatically
39
    from the class constructor
40

41
    >>> d = {0: {1: {'weight':1}}} # dict-of-dicts single edge (0,1)
42
    >>> G = nx.Graph(d)
43

44
    instead of the equivalent
45

46
    >>> G = nx.from_dict_of_dicts(d)
47

48
    Parameters
49
    ----------
50
    data : object to be converted
51

52
        Current known types are:
53
         any NetworkX graph
54
         dict-of-dicts
55
         dict-of-lists
56
         list 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(data.adj,
77
                                        create_using=create_using,
78
                                        multigraph_input=data.is_multigraph())
79
            if hasattr(data, 'graph'):  # data.graph should be dict-like
80
                result.graph.update(data.graph)
81
            if hasattr(data, 'nodes'):  # data.nodes should be dict-like
82
                # result.add_node_from(data.nodes.items()) possible but
83
                # for custom node_attr_dict_factory which may be hashable
84
                # will be unexpected behavior
85
                for n, dd in data.nodes.items():
86
                    result._node[n].update(dd)
87
            return result
88
        except:
89
            raise nx.NetworkXError("Input is not a correct NetworkX graph.")
90

    
91
    # pygraphviz  agraph
92
    if hasattr(data, "is_strict"):
93
        try:
94
            return nx.nx_agraph.from_agraph(data, create_using=create_using)
95
        except:
96
            raise nx.NetworkXError("Input is not a correct pygraphviz graph.")
97

    
98
    # dict of dicts/lists
99
    if isinstance(data, dict):
100
        try:
101
            return from_dict_of_dicts(data, create_using=create_using,
102
                                      multigraph_input=multigraph_input)
103
        except:
104
            try:
105
                return from_dict_of_lists(data, create_using=create_using)
106
            except:
107
                raise TypeError("Input is not known type.")
108

    
109
    # list or generator of edges
110

    
111
    if (isinstance(data, (list, tuple)) or
112
            any(hasattr(data, attr) for attr in ['_adjdict', 'next', '__next__'])):
113
        try:
114
            return from_edgelist(data, create_using=create_using)
115
        except:
116
            raise nx.NetworkXError("Input is not a valid edge list")
117

    
118
    # Pandas DataFrame
119
    try:
120
        import pandas as pd
121
        if isinstance(data, pd.DataFrame):
122
            if data.shape[0] == data.shape[1]:
123
                try:
124
                    return nx.from_pandas_adjacency(data, create_using=create_using)
125
                except:
126
                    msg = "Input is not a correct Pandas DataFrame adjacency matrix."
127
                    raise nx.NetworkXError(msg)
128
            else:
129
                try:
130
                    return nx.from_pandas_edgelist(data, edge_attr=True, create_using=create_using)
131
                except:
132
                    msg = "Input is not a correct Pandas DataFrame edge-list."
133
                    raise nx.NetworkXError(msg)
134
    except ImportError:
135
        msg = 'pandas not found, skipping conversion test.'
136
        warnings.warn(msg, ImportWarning)
137

    
138
    # numpy matrix or ndarray
139
    try:
140
        import numpy
141
        if isinstance(data, (numpy.matrix, numpy.ndarray)):
142
            try:
143
                return nx.from_numpy_matrix(data, create_using=create_using)
144
            except:
145
                raise nx.NetworkXError(
146
                    "Input is not a correct numpy matrix or array.")
147
    except ImportError:
148
        warnings.warn('numpy not found, skipping conversion test.',
149
                      ImportWarning)
150

    
151
    # scipy sparse matrix - any format
152
    try:
153
        import scipy
154
        if hasattr(data, "format"):
155
            try:
156
                return nx.from_scipy_sparse_matrix(data, create_using=create_using)
157
            except:
158
                raise nx.NetworkXError(
159
                    "Input is not a correct scipy sparse matrix type.")
160
    except ImportError:
161
        warnings.warn('scipy not found, skipping conversion test.',
162
                      ImportWarning)
163

    
164
    raise nx.NetworkXError(
165
        "Input is not a known data type for conversion.")
166

    
167

    
168
def to_dict_of_lists(G, nodelist=None):
169
    """Returns adjacency representation of graph as a dictionary of lists.
170

171
    Parameters
172
    ----------
173
    G : graph
174
       A NetworkX graph
175

176
    nodelist : list
177
       Use only nodes specified in nodelist
178

179
    Notes
180
    -----
181
    Completely ignores edge data for MultiGraph and MultiDiGraph.
182

183
    """
184
    if nodelist is None:
185
        nodelist = G
186

    
187
    d = {}
188
    for n in nodelist:
189
        d[n] = [nbr for nbr in G.neighbors(n) if nbr in nodelist]
190
    return d
191

    
192

    
193
def from_dict_of_lists(d, create_using=None):
194
    """Returns a graph from a dictionary of lists.
195

196
    Parameters
197
    ----------
198
    d : dictionary of lists
199
      A dictionary of lists adjacency representation.
200

201
    create_using : NetworkX graph constructor, optional (default=nx.Graph)
202
        Graph type to create. If graph instance, then cleared before populated.
203

204
    Examples
205
    --------
206
    >>> dol = {0: [1]} # single edge (0,1)
207
    >>> G = nx.from_dict_of_lists(dol)
208

209
    or
210

211
    >>> G = nx.Graph(dol) # use Graph constructor
212

213
    """
214
    G = nx.empty_graph(0, create_using)
215
    G.add_nodes_from(d)
216
    if G.is_multigraph() and not G.is_directed():
217
        # a dict_of_lists can't show multiedges.  BUT for undirected graphs,
218
        # each edge shows up twice in the dict_of_lists.
219
        # So we need to treat this case separately.
220
        seen = {}
221
        for node, nbrlist in d.items():
222
            for nbr in nbrlist:
223
                if nbr not in seen:
224
                    G.add_edge(node, nbr)
225
            seen[node] = 1  # don't allow reverse edge to show up
226
    else:
227
        G.add_edges_from(((node, nbr) for node, nbrlist in d.items()
228
                          for nbr in nbrlist))
229
    return G
230

    
231

    
232
def to_dict_of_dicts(G, nodelist=None, edge_data=None):
233
    """Returns adjacency representation of graph as a dictionary of dictionaries.
234

235
    Parameters
236
    ----------
237
    G : graph
238
       A NetworkX graph
239

240
    nodelist : list
241
       Use only nodes specified in nodelist
242

243
    edge_data : list, optional
244
       If provided,  the value of the dictionary will be
245
       set to edge_data for all edges.  This is useful to make
246
       an adjacency matrix type representation with 1 as the edge data.
247
       If edgedata is None, the edgedata in G is used to fill the values.
248
       If G is a multigraph, the edgedata is a dict for each pair (u,v).
249
    """
250
    dod = {}
251
    if nodelist is None:
252
        if edge_data is None:
253
            for u, nbrdict in G.adjacency():
254
                dod[u] = nbrdict.copy()
255
        else:  # edge_data is not None
256
            for u, nbrdict in G.adjacency():
257
                dod[u] = dod.fromkeys(nbrdict, edge_data)
258
    else:  # nodelist is not None
259
        if edge_data is None:
260
            for u in nodelist:
261
                dod[u] = {}
262
                for v, data in ((v, data) for v, data in G[u].items() if v in nodelist):
263
                    dod[u][v] = data
264
        else:  # nodelist and edge_data are not None
265
            for u in nodelist:
266
                dod[u] = {}
267
                for v in (v for v in G[u] if v in nodelist):
268
                    dod[u][v] = edge_data
269
    return dod
270

    
271

    
272
def from_dict_of_dicts(d, create_using=None, multigraph_input=False):
273
    """Returns a graph from a dictionary of dictionaries.
274

275
    Parameters
276
    ----------
277
    d : dictionary of dictionaries
278
      A dictionary of dictionaries adjacency representation.
279

280
    create_using : NetworkX graph constructor, optional (default=nx.Graph)
281
        Graph type to create. If graph instance, then cleared before populated.
282

283
    multigraph_input : bool (default False)
284
       When True, the values of the inner dict are assumed
285
       to be containers of edge data for multiple edges.
286
       Otherwise this routine assumes the edge data are singletons.
287

288
    Examples
289
    --------
290
    >>> dod = {0: {1: {'weight': 1}}} # single edge (0,1)
291
    >>> G = nx.from_dict_of_dicts(dod)
292

293
    or
294

295
    >>> G = nx.Graph(dod) # use Graph constructor
296

297
    """
298
    G = nx.empty_graph(0, create_using)
299
    G.add_nodes_from(d)
300
    # is dict a MultiGraph or MultiDiGraph?
301
    if multigraph_input:
302
        # make a copy of the list of edge data (but not the edge data)
303
        if G.is_directed():
304
            if G.is_multigraph():
305
                G.add_edges_from((u, v, key, data)
306
                                 for u, nbrs in d.items()
307
                                 for v, datadict in nbrs.items()
308
                                 for key, data in datadict.items())
309
            else:
310
                G.add_edges_from((u, v, data)
311
                                 for u, nbrs in d.items()
312
                                 for v, datadict in nbrs.items()
313
                                 for key, data in datadict.items())
314
        else:  # Undirected
315
            if G.is_multigraph():
316
                seen = set()   # don't add both directions of undirected graph
317
                for u, nbrs in d.items():
318
                    for v, datadict in nbrs.items():
319
                        if (u, v) not in seen:
320
                            G.add_edges_from((u, v, key, data)
321
                                             for key, data in datadict.items())
322
                            seen.add((v, u))
323
            else:
324
                seen = set()   # don't add both directions of undirected graph
325
                for u, nbrs in d.items():
326
                    for v, datadict in nbrs.items():
327
                        if (u, v) not in seen:
328
                            G.add_edges_from((u, v, data)
329
                                             for key, data in datadict.items())
330
                            seen.add((v, u))
331

    
332
    else:  # not a multigraph to multigraph transfer
333
        if G.is_multigraph() and not G.is_directed():
334
            # d can have both representations u-v, v-u in dict.  Only add one.
335
            # We don't need this check for digraphs since we add both directions,
336
            # or for Graph() since it is done implicitly (parallel edges not allowed)
337
            seen = set()
338
            for u, nbrs in d.items():
339
                for v, data in nbrs.items():
340
                    if (u, v) not in seen:
341
                        G.add_edge(u, v, key=0)
342
                        G[u][v][0].update(data)
343
                    seen.add((v, u))
344
        else:
345
            G.add_edges_from(((u, v, data)
346
                              for u, nbrs in d.items()
347
                              for v, data in nbrs.items()))
348
    return G
349

    
350

    
351
def to_edgelist(G, nodelist=None):
352
    """Returns a list of edges in the graph.
353

354
    Parameters
355
    ----------
356
    G : graph
357
       A NetworkX graph
358

359
    nodelist : list
360
       Use only nodes specified in nodelist
361

362
    """
363
    if nodelist is None:
364
        return G.edges(data=True)
365
    return G.edges(nodelist, data=True)
366

    
367

    
368
def from_edgelist(edgelist, create_using=None):
369
    """Returns a graph from a list of edges.
370

371
    Parameters
372
    ----------
373
    edgelist : list or iterator
374
      Edge tuples
375

376
    create_using : NetworkX graph constructor, optional (default=nx.Graph)
377
        Graph type to create. If graph instance, then cleared before populated.
378

379
    Examples
380
    --------
381
    >>> edgelist = [(0, 1)] # single edge (0,1)
382
    >>> G = nx.from_edgelist(edgelist)
383

384
    or
385

386
    >>> G = nx.Graph(edgelist) # use Graph constructor
387

388
    """
389
    G = nx.empty_graph(0, create_using)
390
    G.add_edges_from(edgelist)
391
    return G