Repository: networkx/networkx

Issue:
Clarification of `networkx.karate_club_graph()` Dataset
> From what I can tell, the "club" entries in the karate club data uses "Club After Fission" (Column 4) of Table 1, which is repeated as "Club After Split From Data" (column 5) in Table 3 of the original paper, which does indeed have "Mr. Hi's" at the 9th row (accommodating for the change of index from 1-based to 0-based), so I don't think there's a bug here. In fact, in comments on #5820, both @dschult and @rossbar confirm this. 

_Originally posted by @ivanov in https://github.com/networkx/networkx/discussions/7515_

### Ref.:
- [`karate_club_graph` docs](https://networkx.org/documentation/stable/reference/generated/networkx.generators.social.karate_club_graph.html)
- Discussion https://github.com/networkx/networkx/discussions/7515 
- issue #5820


Discussion:
dschult: Thanks for this!
Could you make the first two lines wrap nicely (within 88 chars for sure and maybe 80  to look nice)?

Patch:
diff --git a/doc/conf.py b/doc/conf.py
index 37ad344d6..ae2609f67 100644
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -155,6 +155,10 @@ html_theme_options = {
         "version_match": "latest" if "dev" in version else version,
     },
     "show_version_warning_banner": True,
+    "analytics": {
+        "plausible_analytics_domain": "networkx.org",
+        "plausible_analytics_url": ("https://views.scientific-python.org/js/script.js"),
+    },
 }
 html_sidebars = {
     "**": ["sidebar-nav-bs", "sidebar-ethical-ads"],
diff --git a/doc/developer/deprecations.rst b/doc/developer/deprecations.rst
index 536ea1ea2..46555e7b7 100644
--- a/doc/developer/deprecations.rst
+++ b/doc/developer/deprecations.rst
@@ -60,4 +60,5 @@ Version 3.6
 ~~~~~~~~~~~
 * Remove ``compute_v_structures`` from ``algorithms/dag.py``.
 * Remove ``link`` kwarg from ``readwrite/json_graph/node_link.py``;
-  Change ``edges`` default value to ``edges``.
+  Remove the ``FutureWarning`` re: the default value of ``edges`` and change the
+  default value to ``"edges"``.
diff --git a/examples/algorithms/plot_girvan_newman.py b/examples/algorithms/plot_girvan_newman.py
index 8b9b01618..8faee0f88 100644
--- a/examples/algorithms/plot_girvan_newman.py
+++ b/examples/algorithms/plot_girvan_newman.py
@@ -31,7 +31,7 @@ modularity_df = pd.DataFrame(
 
 # function to create node colour list
 def create_community_node_colors(graph, communities):
-    number_of_colors = len(communities[0])
+    number_of_colors = len(communities)
     colors = ["#D4FCB1", "#CDC5FC", "#FFC2C4", "#F2D140", "#BCC6C8"][:number_of_colors]
     node_colors = []
     for node in graph:
diff --git a/examples/algorithms/plot_maximum_independent_set.py b/examples/algorithms/plot_maximum_independent_set.py
index 670edf965..f6a3b4f77 100644
--- a/examples/algorithms/plot_maximum_independent_set.py
+++ b/examples/algorithms/plot_maximum_independent_set.py
@@ -35,7 +35,7 @@ G = nx.Graph(
 I = approx.maximum_independent_set(G)
 print(f"Maximum independent set of G: {I}")
 
-pos = nx.spring_layout(G, seed=39299899)
+pos = nx.spring_layout(G, iterations=100, seed=42)
 nx.draw(
     G,
     pos=pos,
diff --git a/networkx/generators/social.py b/networkx/generators/social.py
index 3691d77c5..f41b2d88b 100644
--- a/networkx/generators/social.py
+++ b/networkx/generators/social.py
@@ -21,6 +21,13 @@ def karate_club_graph():
     belongs, either 'Mr. Hi' or 'Officer'. Each edge has a weight based on the
     number of contexts in which that edge's incident node members interacted.
 
+    The dataset is derived from the 'Club After Split From Data' column of Table 3 in [1]_.
+    This was in turn derived from the 'Club After Fission' column of Table 1 in the
+    same paper. Note that the nodes are 0-indexed in NetworkX, but 1-indexed in the
+    paper (the 'Individual Number in Matrix C' column of Table 3 starts at 1). This
+    means, for example, that ``G.nodes[9]["club"]`` returns 'Officer', which
+    corresponds to row 10 of Table 3 in the paper.
+
     Examples
     --------
     To get the name of the club to which a node belongs::
diff --git a/networkx/readwrite/json_graph/node_link.py b/networkx/readwrite/json_graph/node_link.py
index e463771b4..63ca9789f 100644
--- a/networkx/readwrite/json_graph/node_link.py
+++ b/networkx/readwrite/json_graph/node_link.py
@@ -74,7 +74,7 @@ def node_link_data(
     --------
     >>> from pprint import pprint
     >>> G = nx.Graph([("A", "B")])
-    >>> data1 = nx.node_link_data(G)
+    >>> data1 = nx.node_link_data(G, edges="edges")
     >>> pprint(data1)
     {'directed': False,
      'edges': [{'source': 'A', 'target': 'B'}],
@@ -89,11 +89,11 @@ def node_link_data(
     >>> s1
     '{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "A"}, {"id": "B"}], "edges": [{"source": "A", "target": "B"}]}'
 
-    A graph can also be serialized by passing `node_link_data` as an encoder function. The two methods are equivalent.
+    A graph can also be serialized by passing `node_link_data` as an encoder function.
 
     >>> s1 = json.dumps(G, default=nx.node_link_data)
     >>> s1
-    '{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "A"}, {"id": "B"}], "edges": [{"source": "A", "target": "B"}]}'
+    '{"directed": false, "multigraph": false, "graph": {}, "nodes": [{"id": "A"}, {"id": "B"}], "links": [{"source": "A", "target": "B"}]}'
 
     The attribute names for storing NetworkX-internal graph data can
     be specified as keyword options.
@@ -119,7 +119,6 @@ def node_link_data(
     To use `node_link_data` in conjunction with `node_link_graph`,
     the keyword names for the attributes must match.
 
-
     See Also
     --------
     node_link_graph, adjacency_data, tree_data
@@ -130,6 +129,7 @@ def node_link_data(
         warnings.warn(
             "Keyword argument 'link' is deprecated; use 'edges' instead",
             DeprecationWarning,
+            stacklevel=2,
         )
         if edges is not None:
             raise ValueError(
@@ -139,7 +139,16 @@ def node_link_data(
             edges = link
     else:
         if edges is None:
-            edges = "edges"
+            warnings.warn(
+                (
+                    '\nThe default value will be `edges="edges" in NetworkX 3.6.\n\n'
+                    "To make this warning go away, explicitly set the edges kwarg, e.g.:\n\n"
+                    '  nx.node_link_data(G, edges="links") to preserve current behavior, or\n'
+                    '  nx.node_link_data(G, edges="edges") for forward compatibility.'
+                ),
+                FutureWarning,
+            )
+            edges = "links"
     # ------------------------------------------------------------
 
     multigraph = G.is_multigraph()
@@ -225,7 +234,7 @@ def node_link_graph(
 
     >>> from pprint import pprint
     >>> G = nx.Graph([("A", "B")])
-    >>> data = nx.node_link_data(G)
+    >>> data = nx.node_link_data(G, edges="edges")
     >>> pprint(data)
     {'directed': False,
      'edges': [{'source': 'A', 'target': 'B'}],
@@ -235,15 +244,15 @@ def node_link_graph(
 
     Revert data in node-link format to a graph.
 
-    >>> H = nx.node_link_graph(data)
+    >>> H = nx.node_link_graph(data, edges="edges")
     >>> print(H.edges)
     [('A', 'B')]
 
     To serialize and deserialize a graph with JSON,
 
     >>> import json
-    >>> d = json.dumps(nx.node_link_data(G))
-    >>> H = nx.node_link_graph(json.loads(d))
+    >>> d = json.dumps(nx.node_link_data(G, edges="edges"))
+    >>> H = nx.node_link_graph(json.loads(d), edges="edges")
     >>> print(G.edges, H.edges)
     [('A', 'B')] [('A', 'B')]
 
@@ -265,6 +274,7 @@ def node_link_graph(
         warnings.warn(
             "Keyword argument 'link' is deprecated; use 'edges' instead",
             DeprecationWarning,
+            stacklevel=2,
         )
         if edges is not None:
             raise ValueError(
@@ -274,7 +284,16 @@ def node_link_graph(
             edges = link
     else:
         if edges is None:
-            edges = "edges"
+            warnings.warn(
+                (
+                    '\nThe default value will be changed to `edges="edges" in NetworkX 3.6.\n\n'
+                    "To make this warning go away, explicitly set the edges kwarg, e.g.:\n\n"
+                    '  nx.node_link_graph(data, edges="links") to preserve current behavior, or\n'
+                    '  nx.node_link_graph(data, edges="edges") for forward compatibility.'
+                ),
+                FutureWarning,
+            )
+            edges = "links"
     # -------------------------------------------------------------
 
     multigraph = data.get("multigraph", multigraph)
diff --git a/pyproject.toml b/pyproject.toml
index 89ac4d02a..cd6b5c915 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -55,10 +55,10 @@ nx_loopback = 'networkx.classes.tests.dispatch_interface:backend_interface'
 
 [project.optional-dependencies]
 default = [
-    'numpy>=1.23',
-    'scipy>=1.9,!=1.11.0,!=1.11.1',
-    'matplotlib>=3.6',
-    'pandas>=1.4',
+    'numpy>=1.24',
+    'scipy>=1.10,!=1.11.0,!=1.11.1',
+    'matplotlib>=3.7',
+    'pandas>=2.0',
 ]
 developer = [
     'changelist==0.5',
@@ -87,7 +87,7 @@ example = [
 ]
 extra = [
     'lxml>=4.6',
-    'pygraphviz>=1.13',
+    'pygraphviz>=1.14',
     'pydot>=3.0.1',
     'sympy>=1.10',
 ]
diff --git a/requirements/default.txt b/requirements/default.txt
index 97e1e259d..5f64c46cb 100644
--- a/requirements/default.txt
+++ b/requirements/default.txt
@@ -1,6 +1,6 @@
 # Generated via tools/generate_requirements.py and pre-commit hook.
 # Do not edit this file; modify pyproject.toml instead.
-numpy>=1.23
-scipy>=1.9,!=1.11.0,!=1.11.1
-matplotlib>=3.6
-pandas>=1.4
+numpy>=1.24
+scipy>=1.10,!=1.11.0,!=1.11.1
+matplotlib>=3.7
+pandas>=2.0
diff --git a/requirements/extra.txt b/requirements/extra.txt
index b4335fafa..5c62cd9ed 100644
--- a/requirements/extra.txt
+++ b/requirements/extra.txt
@@ -1,6 +1,6 @@
 # Generated via tools/generate_requirements.py and pre-commit hook.
 # Do not edit this file; modify pyproject.toml instead.
 lxml>=4.6
-pygraphviz>=1.13
+pygraphviz>=1.14
 pydot>=3.0.1
 sympy>=1.10


Test patch:
diff --git a/networkx/readwrite/json_graph/tests/test_node_link.py b/networkx/readwrite/json_graph/tests/test_node_link.py
index 561a79c22..f903f6066 100644
--- a/networkx/readwrite/json_graph/tests/test_node_link.py
+++ b/networkx/readwrite/json_graph/tests/test_node_link.py
@@ -6,6 +6,23 @@ import networkx as nx
 from networkx.readwrite.json_graph import node_link_data, node_link_graph
 
 
+def test_node_link_edges_default_future_warning():
+    "Test FutureWarning is raised when `edges=None` in node_link_data and node_link_graph"
+    G = nx.Graph([(1, 2)])
+    with pytest.warns(FutureWarning, match="\nThe default value will be"):
+        data = nx.node_link_data(G)  # edges=None, the default
+    with pytest.warns(FutureWarning, match="\nThe default value will be"):
+        H = nx.node_link_graph(data)  # edges=None, the default
+
+
+def test_node_link_deprecated_link_param():
+    G = nx.Graph([(1, 2)])
+    with pytest.warns(DeprecationWarning, match="Keyword argument 'link'"):
+        data = nx.node_link_data(G, link="links")
+    with pytest.warns(DeprecationWarning, match="Keyword argument 'link'"):
+        H = nx.node_link_graph(data, link="links")
+
+
 class TestNodeLink:
     # TODO: To be removed when signature change complete
     def test_custom_attrs_dep(self):
@@ -43,13 +60,15 @@ class TestNodeLink:
         assert H[1][2]["width"] == 7
 
     def test_exception_dep(self):
+        G = nx.MultiDiGraph()
         with pytest.raises(nx.NetworkXError):
-            G = nx.MultiDiGraph()
-            node_link_data(G, name="node", source="node", target="node", key="node")
+            with pytest.warns(FutureWarning, match="\nThe default value will be"):
+                node_link_data(G, name="node", source="node", target="node", key="node")
 
     def test_graph(self):
         G = nx.path_graph(4)
-        H = node_link_graph(node_link_data(G))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(node_link_data(G))
         assert nx.is_isomorphic(G, H)
 
     def test_graph_attributes(self):
@@ -59,13 +78,16 @@ class TestNodeLink:
         G.graph[1] = "one"
         G.graph["foo"] = "bar"
 
-        H = node_link_graph(node_link_data(G))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(node_link_data(G))
         assert H.graph["foo"] == "bar"
         assert H.nodes[1]["color"] == "red"
         assert H[1][2]["width"] == 7
 
-        d = json.dumps(node_link_data(G))
-        H = node_link_graph(json.loads(d))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            d = json.dumps(node_link_data(G))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(json.loads(d))
         assert H.graph["foo"] == "bar"
         assert H.graph["1"] == "one"
         assert H.nodes[1]["color"] == "red"
@@ -73,24 +95,28 @@ class TestNodeLink:
 
     def test_digraph(self):
         G = nx.DiGraph()
-        H = node_link_graph(node_link_data(G))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(node_link_data(G))
         assert H.is_directed()
 
     def test_multigraph(self):
         G = nx.MultiGraph()
         G.add_edge(1, 2, key="first")
         G.add_edge(1, 2, key="second", color="blue")
-        H = node_link_graph(node_link_data(G))
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(node_link_data(G))
         assert nx.is_isomorphic(G, H)
         assert H[1][2]["second"]["color"] == "blue"
 
     def test_graph_with_tuple_nodes(self):
         G = nx.Graph()
         G.add_edge((0, 0), (1, 0), color=[255, 255, 0])
-        d = node_link_data(G)
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            d = node_link_data(G)
         dumped_d = json.dumps(d)
         dd = json.loads(dumped_d)
-        H = node_link_graph(dd)
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(dd)
         assert H.nodes[(0, 0)] == G.nodes[(0, 0)]
         assert H[(0, 0)][(1, 0)]["color"] == [255, 255, 0]
 
@@ -98,17 +124,20 @@ class TestNodeLink:
         q = "qualité"
         G = nx.Graph()
         G.add_node(1, **{q: q})
-        s = node_link_data(G)
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            s = node_link_data(G)
         output = json.dumps(s, ensure_ascii=False)
         data = json.loads(output)
-        H = node_link_graph(data)
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(data)
         assert H.nodes[1][q] == q
 
     def test_exception(self):
+        G = nx.MultiDiGraph()
+        attrs = {"name": "node", "source": "node", "target": "node", "key": "node"}
         with pytest.raises(nx.NetworkXError):
-            G = nx.MultiDiGraph()
-            attrs = {"name": "node", "source": "node", "target": "node", "key": "node"}
-            node_link_data(G, **attrs)
+            with pytest.warns(FutureWarning, match="\nThe default value will be"):
+                node_link_data(G, **attrs)
 
     def test_string_ids(self):
         q = "qualité"
@@ -116,10 +145,12 @@ class TestNodeLink:
         G.add_node("A")
         G.add_node(q)
         G.add_edge("A", q)
-        data = node_link_data(G)
-        assert data["edges"][0]["source"] == "A"
-        assert data["edges"][0]["target"] == q
-        H = node_link_graph(data)
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            data = node_link_data(G)
+        assert data["links"][0]["source"] == "A"
+        assert data["links"][0]["target"] == q
+        with pytest.warns(FutureWarning, match="\nThe default value will be"):
+            H = node_link_graph(data)
         assert nx.is_isomorphic(G, H)
 
     def test_custom_attrs(self):