summaryrefslogtreecommitdiff
path: root/networkx/convert_matrix.py
diff options
context:
space:
mode:
Diffstat (limited to 'networkx/convert_matrix.py')
-rw-r--r--networkx/convert_matrix.py200
1 files changed, 132 insertions, 68 deletions
diff --git a/networkx/convert_matrix.py b/networkx/convert_matrix.py
index 0746af7c..4a3dacb7 100644
--- a/networkx/convert_matrix.py
+++ b/networkx/convert_matrix.py
@@ -25,16 +25,30 @@ import itertools
import networkx as nx
from networkx.utils import not_implemented_for
-__all__ = ['from_numpy_matrix', 'to_numpy_matrix',
- 'from_pandas_adjacency', 'to_pandas_adjacency',
- 'from_pandas_edgelist', 'to_pandas_edgelist',
- 'to_numpy_recarray',
- 'from_scipy_sparse_matrix', 'to_scipy_sparse_matrix',
- 'from_numpy_array', 'to_numpy_array']
-
-
-def to_pandas_adjacency(G, nodelist=None, dtype=None, order=None,
- multigraph_weight=sum, weight='weight', nonedge=0.0):
+__all__ = [
+ "from_numpy_matrix",
+ "to_numpy_matrix",
+ "from_pandas_adjacency",
+ "to_pandas_adjacency",
+ "from_pandas_edgelist",
+ "to_pandas_edgelist",
+ "to_numpy_recarray",
+ "from_scipy_sparse_matrix",
+ "to_scipy_sparse_matrix",
+ "from_numpy_array",
+ "to_numpy_array",
+]
+
+
+def to_pandas_adjacency(
+ G,
+ nodelist=None,
+ dtype=None,
+ order=None,
+ multigraph_weight=sum,
+ weight="weight",
+ nonedge=0.0,
+):
"""Returns the graph adjacency matrix as a Pandas DataFrame.
Parameters
@@ -117,9 +131,16 @@ def to_pandas_adjacency(G, nodelist=None, dtype=None, order=None,
"""
import pandas as pd
- M = to_numpy_array(G, nodelist=nodelist, dtype=dtype, order=order,
- multigraph_weight=multigraph_weight, weight=weight,
- nonedge=nonedge)
+
+ M = to_numpy_array(
+ G,
+ nodelist=nodelist,
+ dtype=dtype,
+ order=order,
+ multigraph_weight=multigraph_weight,
+ weight=weight,
+ nonedge=nonedge,
+ )
if nodelist is None:
nodelist = list(G)
return pd.DataFrame(data=M, index=nodelist, columns=nodelist)
@@ -190,8 +211,9 @@ def from_pandas_adjacency(df, create_using=None):
return G
-def to_pandas_edgelist(G, source='source', target='target', nodelist=None,
- dtype=None, order=None):
+def to_pandas_edgelist(
+ G, source="source", target="target", nodelist=None, dtype=None, order=None
+):
"""Returns the graph edge list as a Pandas DataFrame.
Parameters
@@ -227,6 +249,7 @@ def to_pandas_edgelist(G, source='source', target='target', nodelist=None,
"""
import pandas as pd
+
if nodelist is None:
edgelist = G.edges(data=True)
else:
@@ -234,15 +257,15 @@ def to_pandas_edgelist(G, source='source', target='target', nodelist=None,
source_nodes = [s for s, t, d in edgelist]
target_nodes = [t for s, t, d in edgelist]
all_keys = set().union(*(d.keys() for s, t, d in edgelist))
- edge_attr = {k: [d.get(k, float("nan")) for s, t, d in edgelist]
- for k in all_keys}
+ edge_attr = {k: [d.get(k, float("nan")) for s, t, d in edgelist] for k in all_keys}
edgelistdict = {source: source_nodes, target: target_nodes}
edgelistdict.update(edge_attr)
return pd.DataFrame(edgelistdict)
-def from_pandas_edgelist(df, source='source', target='target', edge_attr=None,
- create_using=None):
+def from_pandas_edgelist(
+ df, source="source", target="target", edge_attr=None, create_using=None
+):
"""Returns a graph from Pandas DataFrame containing an edge list.
The Pandas DataFrame should contain at least two columns of node names and
@@ -347,8 +370,15 @@ def from_pandas_edgelist(df, source='source', target='target', edge_attr=None,
return g
-def to_numpy_matrix(G, nodelist=None, dtype=None, order=None,
- multigraph_weight=sum, weight='weight', nonedge=0.0):
+def to_numpy_matrix(
+ G,
+ nodelist=None,
+ dtype=None,
+ order=None,
+ multigraph_weight=sum,
+ weight="weight",
+ nonedge=0.0,
+):
"""Returns the graph adjacency matrix as a NumPy matrix.
Parameters
@@ -442,9 +472,15 @@ def to_numpy_matrix(G, nodelist=None, dtype=None, order=None,
"""
import numpy as np
- A = to_numpy_array(G, nodelist=nodelist, dtype=dtype, order=order,
- multigraph_weight=multigraph_weight, weight=weight,
- nonedge=nonedge)
+ A = to_numpy_array(
+ G,
+ nodelist=nodelist,
+ dtype=dtype,
+ order=order,
+ multigraph_weight=multigraph_weight,
+ weight=weight,
+ nonedge=nonedge,
+ )
M = np.asmatrix(A, dtype=dtype)
return M
@@ -536,18 +572,21 @@ def from_numpy_matrix(A, parallel_edges=False, create_using=None):
"""
# This should never fail if you have created a numpy matrix with numpy...
import numpy as np
- kind_to_python_type = {'f': float,
- 'i': int,
- 'u': int,
- 'b': bool,
- 'c': complex,
- 'S': str,
- 'V': 'void'}
- kind_to_python_type['U'] = str
+
+ kind_to_python_type = {
+ "f": float,
+ "i": int,
+ "u": int,
+ "b": bool,
+ "c": complex,
+ "S": str,
+ "V": "void",
+ }
+ kind_to_python_type["U"] = str
G = nx.empty_graph(0, create_using)
n, m = A.shape
if n != m:
- raise nx.NetworkXError('Adjacency matrix is not square.', f"nx,ny={A.shape}")
+ raise nx.NetworkXError("Adjacency matrix is not square.", f"nx,ny={A.shape}")
dt = A.dtype
try:
python_type = kind_to_python_type[dt.kind]
@@ -558,16 +597,24 @@ def from_numpy_matrix(A, parallel_edges=False, create_using=None):
G.add_nodes_from(range(n))
# Get a list of all the entries in the matrix with nonzero entries. These
# coordinates will become the edges in the graph.
- edges = map(lambda e: (int(e[0]), int(e[1])),
- zip(*(np.asarray(A).nonzero())))
+ edges = map(lambda e: (int(e[0]), int(e[1])), zip(*(np.asarray(A).nonzero())))
# handle numpy constructed data type
- if python_type == 'void':
+ if python_type == "void":
# Sort the fields by their offset, then by dtype, then by name.
- fields = sorted((offset, dtype, name) for name, (dtype, offset) in
- A.dtype.fields.items())
- triples = ((u, v, {name: kind_to_python_type[dtype.kind](val)
- for (_, dtype, name), val in zip(fields, A[u, v])})
- for u, v in edges)
+ fields = sorted(
+ (offset, dtype, name) for name, (dtype, offset) in A.dtype.fields.items()
+ )
+ triples = (
+ (
+ u,
+ v,
+ {
+ name: kind_to_python_type[dtype.kind](val)
+ for (_, dtype, name), val in zip(fields, A[u, v])
+ },
+ )
+ for u, v in edges
+ )
# If the entries in the adjacency matrix are integers, the graph is a
# multigraph, and parallel_edges is True, then create parallel edges, each
# with weight 1, for each entry in the adjacency matrix. Otherwise, create
@@ -581,11 +628,11 @@ def from_numpy_matrix(A, parallel_edges=False, create_using=None):
# for d in range(A[u, v]):
# G.add_edge(u, v, weight=1)
#
- triples = chain(((u, v, dict(weight=1)) for d in range(A[u, v]))
- for (u, v) in edges)
+ triples = chain(
+ ((u, v, dict(weight=1)) for d in range(A[u, v])) for (u, v) in edges
+ )
else: # basic data type
- triples = ((u, v, dict(weight=python_type(A[u, v])))
- for u, v in edges)
+ triples = ((u, v, dict(weight=python_type(A[u, v]))) for u, v in edges)
# If we are creating an undirected multigraph, only add the edges from the
# upper triangle of the matrix. Otherwise, add all the edges. This relies
# on the fact that the vertices created in the
@@ -600,7 +647,7 @@ def from_numpy_matrix(A, parallel_edges=False, create_using=None):
return G
-@not_implemented_for('multigraph')
+@not_implemented_for("multigraph")
def to_numpy_recarray(G, nodelist=None, dtype=None, order=None):
"""Returns the graph adjacency matrix as a NumPy recarray.
@@ -647,8 +694,9 @@ def to_numpy_recarray(G, nodelist=None, dtype=None, order=None):
"""
if dtype is None:
- dtype = [('weight', float)]
+ dtype = [("weight", float)]
import numpy as np
+
if nodelist is None:
nodelist = list(G)
nodeset = set(nodelist)
@@ -672,8 +720,7 @@ def to_numpy_recarray(G, nodelist=None, dtype=None, order=None):
return M.view(np.recarray)
-def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
- weight='weight', format='csr'):
+def to_scipy_sparse_matrix(G, nodelist=None, dtype=None, weight="weight", format="csr"):
"""Returns the graph adjacency matrix as a SciPy sparse matrix.
Parameters
@@ -757,6 +804,7 @@ def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
https://docs.scipy.org/doc/scipy/reference/sparse.html
"""
from scipy import sparse
+
if nodelist is None:
nodelist = list(G)
nlen = len(nodelist)
@@ -768,9 +816,13 @@ def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
raise nx.NetworkXError(msg)
index = dict(zip(nodelist, range(nlen)))
- coefficients = zip(*((index[u], index[v], d.get(weight, 1))
- for u, v, d in G.edges(nodelist, data=True)
- if u in index and v in index))
+ coefficients = zip(
+ *(
+ (index[u], index[v], d.get(weight, 1))
+ for u, v, d in G.edges(nodelist, data=True)
+ if u in index and v in index
+ )
+ )
try:
row, col, data = coefficients
except ValueError:
@@ -778,8 +830,7 @@ def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
row, col, data = [], [], []
if G.is_directed():
- M = sparse.coo_matrix((data, (row, col)),
- shape=(nlen, nlen), dtype=dtype)
+ M = sparse.coo_matrix((data, (row, col)), shape=(nlen, nlen), dtype=dtype)
else:
# symmetrize matrix
d = data + data
@@ -789,9 +840,13 @@ def to_scipy_sparse_matrix(G, nodelist=None, dtype=None,
# so we subtract the data on the diagonal
selfloops = list(nx.selfloop_edges(G, data=True))
if selfloops:
- diag_index, diag_data = zip(*((index[u], -d.get(weight, 1))
- for u, v, d in selfloops
- if u in index and v in index))
+ diag_index, diag_data = zip(
+ *(
+ (index[u], -d.get(weight, 1))
+ for u, v, d in selfloops
+ if u in index and v in index
+ )
+ )
d += diag_data
r += diag_index
c += diag_index
@@ -853,18 +908,19 @@ def _generate_weighted_edges(A):
`A` is a SciPy sparse matrix (in any format).
"""
- if A.format == 'csr':
+ if A.format == "csr":
return _csr_gen_triples(A)
- if A.format == 'csc':
+ if A.format == "csc":
return _csc_gen_triples(A)
- if A.format == 'dok':
+ if A.format == "dok":
return _dok_gen_triples(A)
# If A is in any other format (including COO), convert it to COO format.
return _coo_gen_triples(A.tocoo())
-def from_scipy_sparse_matrix(A, parallel_edges=False, create_using=None,
- edge_attribute='weight'):
+def from_scipy_sparse_matrix(
+ A, parallel_edges=False, create_using=None, edge_attribute="weight"
+):
"""Creates a new graph from an adjacency matrix given as a SciPy sparse
matrix.
@@ -942,7 +998,7 @@ def from_scipy_sparse_matrix(A, parallel_edges=False, create_using=None,
# with weight 1, for each entry in the adjacency matrix. Otherwise, create
# one edge for each positive entry in the adjacency matrix and set the
# weight of that edge to be the entry in the matrix.
- if A.dtype.kind in ('i', 'u') and G.is_multigraph() and parallel_edges:
+ if A.dtype.kind in ("i", "u") and G.is_multigraph() and parallel_edges:
chain = itertools.chain.from_iterable
# The following line is equivalent to:
#
@@ -965,8 +1021,15 @@ def from_scipy_sparse_matrix(A, parallel_edges=False, create_using=None,
return G
-def to_numpy_array(G, nodelist=None, dtype=None, order=None,
- multigraph_weight=sum, weight='weight', nonedge=0.0):
+def to_numpy_array(
+ G,
+ nodelist=None,
+ dtype=None,
+ order=None,
+ multigraph_weight=sum,
+ weight="weight",
+ nonedge=0.0,
+):
"""Returns the graph adjacency matrix as a NumPy array.
Parameters
@@ -1111,7 +1174,7 @@ def to_numpy_array(G, nodelist=None, dtype=None, order=None,
try:
op = operator[multigraph_weight]
except Exception:
- raise ValueError('multigraph_weight must be sum, min, or max')
+ raise ValueError("multigraph_weight must be sum, min, or max")
for u, v, attrs in G.edges(data=True):
if (u in nodeset) and (v in nodeset):
@@ -1225,5 +1288,6 @@ def from_numpy_array(A, parallel_edges=False, create_using=None):
1.0
"""
- return from_numpy_matrix(A, parallel_edges=parallel_edges,
- create_using=create_using)
+ return from_numpy_matrix(
+ A, parallel_edges=parallel_edges, create_using=create_using
+ )