summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--networkx/algorithms/assortativity/neighbor_degree.py74
-rw-r--r--networkx/algorithms/assortativity/tests/test_neighbor_degree.py27
2 files changed, 57 insertions, 44 deletions
diff --git a/networkx/algorithms/assortativity/neighbor_degree.py b/networkx/algorithms/assortativity/neighbor_degree.py
index 84dffd8f..3a9ed8d5 100644
--- a/networkx/algorithms/assortativity/neighbor_degree.py
+++ b/networkx/algorithms/assortativity/neighbor_degree.py
@@ -1,23 +1,6 @@
__all__ = ["average_neighbor_degree"]
-def _average_nbr_deg(G, source_degree, target_degree, nodes=None, weight=None):
- # average degree of neighbors
- avg = {}
- for n, deg in source_degree(nodes, weight=weight):
- # normalize but not by zero degree
- if deg == 0:
- deg = 1
- nbrdeg = target_degree(G[n])
- if weight is None:
- avg[n] = sum(d for n, d in nbrdeg) / float(deg)
- else:
- avg[n] = sum((G[n][nbr].get(weight, 1) * d for nbr, d in nbrdeg)) / float(
- deg
- )
- return avg
-
-
def average_neighbor_degree(G, source="out", target="out", nodes=None, weight=None):
r"""Returns the average degree of the neighborhood of each node.
@@ -44,11 +27,11 @@ def average_neighbor_degree(G, source="out", target="out", nodes=None, weight=No
----------
G : NetworkX graph
- source : string ("in"|"out")
+ source : string ("in"|"out"|"in+out")
Directed graphs only.
Use "in"- or "out"-degree for source node.
- target : string ("in"|"out")
+ target : string ("in"|"out"|"in+out")
Directed graphs only.
Use "in"- or "out"-degree for target node.
@@ -79,7 +62,7 @@ def average_neighbor_degree(G, source="out", target="out", nodes=None, weight=No
>>> G = nx.DiGraph()
>>> nx.add_path(G, [0, 1, 2, 3])
>>> nx.average_neighbor_degree(G, source="in", target="in")
- {0: 1.0, 1: 1.0, 2: 1.0, 3: 0.0}
+ {0: 0.0, 1: 1.0, 2: 1.0, 3: 0.0}
>>> nx.average_neighbor_degree(G, source="out", target="out")
{0: 1.0, 1: 1.0, 2: 0.0, 3: 0.0}
@@ -102,21 +85,36 @@ def average_neighbor_degree(G, source="out", target="out", nodes=None, weight=No
source_degree = G.degree
target_degree = G.degree
if G.is_directed():
- direction = {"out": G.out_degree, "in": G.in_degree}
- source_degree = direction[source]
- target_degree = direction[target]
- return _average_nbr_deg(G, source_degree, target_degree, nodes=nodes, weight=weight)
-
-
-# obsolete
-# def average_neighbor_in_degree(G, nodes=None, weight=None):
-# if not G.is_directed():
-# raise nx.NetworkXError("Not defined for undirected graphs.")
-# return _average_nbr_deg(G, G.in_degree, G.in_degree, nodes, weight)
-# average_neighbor_in_degree.__doc__=average_neighbor_degree.__doc__
-
-# def average_neighbor_out_degree(G, nodes=None, weight=None):
-# if not G.is_directed():
-# raise nx.NetworkXError("Not defined for undirected graphs.")
-# return _average_nbr_deg(G, G.out_degree, G.out_degree, nodes, weight)
-# average_neighbor_out_degree.__doc__=average_neighbor_degree.__doc__
+ if source == "in":
+ source_degree = G.in_degree
+ elif source == "out":
+ source_degree = G.out_degree
+ elif source != "in+out":
+ raise nx.NetworkXError(
+ f"source argument {source} must be 'in', 'out' or 'in+out'"
+ )
+
+ if target == "in":
+ target_degree = G.in_degree
+ elif target == "out":
+ target_degree = G.out_degree
+ elif target != "in+out":
+ raise nx.NetworkXError(
+ f"target argument {target} must be 'in', 'out' or 'in+out'"
+ )
+
+ # precompute target degrees -- should *not* be weighted degree
+ tgt_deg = dict(target_degree())
+ # average degree of neighbors
+ avg = {}
+ for n, deg in source_degree(nodes, weight=weight):
+ # normalize but not by zero degree
+ if deg == 0:
+ avg[n] = 0.0
+ continue
+ G_n = G[n]
+ if weight is None:
+ avg[n] = sum(tgt_deg[nbr] for nbr in G_n) / deg
+ else:
+ avg[n] = sum(G_n[nbr].get(weight, 1) * tgt_deg[nbr] for nbr in G_n) / deg
+ return avg
diff --git a/networkx/algorithms/assortativity/tests/test_neighbor_degree.py b/networkx/algorithms/assortativity/tests/test_neighbor_degree.py
index 65827da1..66d39b9a 100644
--- a/networkx/algorithms/assortativity/tests/test_neighbor_degree.py
+++ b/networkx/algorithms/assortativity/tests/test_neighbor_degree.py
@@ -13,13 +13,15 @@ class TestAverageNeighbor:
nd = nx.average_neighbor_degree(D)
assert nd == answer
- D = G.to_directed()
+ D = nx.DiGraph(G.edges(data=True))
nd = nx.average_neighbor_degree(D)
- assert nd == answer
-
- D = G.to_directed()
- nd = nx.average_neighbor_degree(D, source="in", target="in")
- assert nd == answer
+ assert nd == {0: 1, 1: 1, 2: 0, 3: 0}
+ nd = nx.average_neighbor_degree(D, "in", "out")
+ assert nd == {0: 0, 1: 1, 2: 0, 3: 0}
+ nd = nx.average_neighbor_degree(D, "out", "in")
+ assert nd == {0: 1, 1: 1, 2: 1, 3: 0}
+ nd = nx.average_neighbor_degree(D, "in", "in")
+ assert nd == {0: 0, 1: 1, 2: 1, 3: 0}
def test_degree_p4_weighted(self):
G = nx.path_graph(4)
@@ -32,6 +34,19 @@ class TestAverageNeighbor:
nd = nx.average_neighbor_degree(D, weight="weight")
assert nd == answer
+ D = nx.DiGraph(G.edges(data=True))
+ print(D.edges(data=True))
+ nd = nx.average_neighbor_degree(D, weight="weight")
+ assert nd == {0: 1, 1: 1, 2: 0, 3: 0}
+ nd = nx.average_neighbor_degree(D, "out", "out", weight="weight")
+ assert nd == {0: 1, 1: 1, 2: 0, 3: 0}
+ nd = nx.average_neighbor_degree(D, "in", "in", weight="weight")
+ assert nd == {0: 0, 1: 4, 2: 0.25, 3: 0}
+ nd = nx.average_neighbor_degree(D, "in", "out", weight="weight")
+ assert nd == {0: 0, 1: 4, 2: 0, 3: 0}
+ nd = nx.average_neighbor_degree(D, "out", "in", weight="weight")
+ assert nd == {0: 1, 1: 1, 2: 1, 3: 0}
+
D = G.to_directed()
nd = nx.average_neighbor_degree(D, weight="weight")
assert nd == answer