diff options
author | Ross Barnowski <rossbar@berkeley.edu> | 2021-09-14 22:40:59 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-14 23:40:59 -0400 |
commit | d7fc10144c624c4ae7fc1c3bc9df7d7a3c563984 (patch) | |
tree | e42c2001cc1463cedd6ca13c179b77fd7aee15ff | |
parent | 4e31e9ee035333d60e02cee4599d7de31ec097a9 (diff) | |
download | networkx-d7fc10144c624c4ae7fc1c3bc9df7d7a3c563984.tar.gz |
Minor updates to tutorial.rst and add docstring for data method of nodes/edges (#5039)
* Rm statement about None as sentinel in Graph.
* Add links to graph gens and readwrite.
* Add links to adjacency reporting properties.
* Rm span kwarg from tutorial example.
Doesn't make sense without more context.
* Add docstring for the NodeView.data method.
* Add docstring for EdgeView.data method
* Add adj dict constructor example.
* Rework some links and add others in DiGraph section.
* Fix autosummary links in tutorial.
* Add headings to graph generator ennumerations.
The enumeration was broken anyways, and this at least makes
the headings more visible and gives them html anchors.
* Add some links to drawing section.
* A few more drawing links.
* Fix doctest.
* Wording update from review.
-rw-r--r-- | doc/tutorial.rst | 103 | ||||
-rw-r--r-- | networkx/classes/reportviews.py | 134 |
2 files changed, 194 insertions, 43 deletions
diff --git a/doc/tutorial.rst b/doc/tutorial.rst index 8f1a1705..ca496560 100644 --- a/doc/tutorial.rst +++ b/doc/tutorial.rst @@ -22,13 +22,14 @@ another Graph, a customized node object, etc. .. note:: Python's ``None`` object is not allowed to be used as a node. It determines whether optional function arguments have been assigned in many - functions. And it can be used as a sentinel object meaning "not a node". + functions. Nodes ----- -The graph ``G`` can be grown in several ways. NetworkX includes many graph -generator functions and facilities to read and write graphs in many formats. +The graph ``G`` can be grown in several ways. NetworkX includes many +:doc:`graph generator functions <reference/generators>` and +:doc:`facilities to read and write graphs in many formats <reference/readwrite/index>`. To get started though we'll look at simple manipulations. You can add one node at a time, @@ -134,9 +135,10 @@ At this stage the graph ``G`` consists of 8 nodes and 3 edges, as can be seen by .. note:: - The order of adjacency reporting (e.g., G.adj, G.successors, - G.predecessors) is the order of edge addition. However, - the order of G.edges is the order of the adjacencies + The order of adjacency reporting (e.g., :meth:`G.adj <networkx.Graph.adj>`, + :meth:`G.successors <networkx.DiGraph.successors>`, + :meth:`G.predecessors <networkx.DiGraph.predecessors>`) is the order of + edge addition. However, the order of G.edges is the order of the adjacencies which includes both the order of the nodes and each node's adjacencies. See example below: @@ -159,7 +161,7 @@ are set-like views of the nodes, edges, neighbors (adjacencies), and degrees of nodes in a graph. They offer a continually updated read-only view into the graph structure. They are also dict-like in that you can look up node and edge data attributes via the views and iterate with data attributes -using methods ``.items()``, ``.data('span')``. +using methods ``.items()``, ``.data()``. If you want a specific container type instead of a view, you can specify one. Here we use lists, though sets, dicts, tuples and other containers may be better in other contexts. @@ -218,11 +220,17 @@ classes you can specify data in several formats. .. nbplot:: >>> G.add_edge(1, 2) - >>> H = nx.DiGraph(G) # create a DiGraph using the connections from G + >>> H = nx.DiGraph(G) # create a DiGraph using the connections from G >>> list(H.edges()) [(1, 2), (2, 1)] >>> edgelist = [(0, 1), (1, 2), (2, 3)] - >>> H = nx.Graph(edgelist) + >>> H = nx.Graph(edgelist) # create a graph from an edge list + >>> list(H.edges()) + [(0, 1), (1, 2), (2, 3)] + >>> adjacency_dict = {0: (1, 2), 1: (0, 2), 2: (0, 1)} + >>> H = nx.Graph(adjacency_dict) # create a Graph dict mapping nodes to nbrs + >>> list(H.edges()) + [(0, 1), (0, 2), (1, 2)] What to use as nodes and edges ------------------------------ @@ -370,11 +378,11 @@ Directed graphs The :class:`DiGraph` class provides additional methods and properties specific to directed edges, e.g., :attr:`DiGraph.out_edges`, :attr:`DiGraph.in_degree`, -:meth:`DiGraph.predecessors`, :meth:`DiGraph.successors` etc. +`DiGraph.predecessors`, `DiGraph.successors` etc. To allow algorithms to work with both classes easily, the directed versions of -``neighbors()`` is equivalent to ``successors()`` while ``degree`` reports -the sum of ``in_degree`` and ``out_degree`` even though that may feel -inconsistent at times. +:meth:`neighbors <DiGraph.neighbors>` is equivalent to +`successors <DiGraph.successors>` while `~DiGraph.degree` reports the sum +of `~DiGraph.in_degree` and `~DiGraph.out_degree` even though that may feel inconsistent at times. .. nbplot:: @@ -435,36 +443,39 @@ In addition to constructing graphs node-by-node or edge-by-edge, they can also be generated by 1. Applying classic graph operations, such as: +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autosummary:: - subgraph - induced subgraph view of G on nodes in nbunch - union - graph union - disjoint_union - graph union assuming all nodes are different - cartesian_product - return Cartesian product graph - compose - combine graphs identifying nodes common to both - complement - graph complement - create_empty_copy - return an empty copy of the same graph class - to_undirected - return an undirected representation of G - to_directed - return a directed representation of G + ~networkx.classes.function.subgraph + ~networkx.algorithms.operators.binary.union + ~networkx.algorithms.operators.binary.disjoint_union + ~networkx.algorithms.operators.product.cartesian_product + ~networkx.algorithms.operators.binary.compose + ~networkx.algorithms.operators.unary.complement + ~networkx.classes.function.create_empty_copy + ~networkx.classes.function.to_undirected + ~networkx.classes.function.to_directed 2. Using a call to one of the classic small graphs, e.g., +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autosummary:: - petersen_graph - tutte_graph - sedgewick_maze_graph - tetrahedral_graph + ~networkx.generators.small.petersen_graph + ~networkx.generators.small.tutte_graph + ~networkx.generators.small.sedgewick_maze_graph + ~networkx.generators.small.tetrahedral_graph 3. Using a (constructive) generator for a classic graph, e.g., +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autosummary:: - complete_graph - complete_bipartite_graph - barbell_graph - lollipop_graph + ~networkx.generators.classic.complete_graph + ~networkx.algorithms.bipartite.generators.complete_bipartite_graph + ~networkx.generators.classic.barbell_graph + ~networkx.generators.classic.lollipop_graph like so: @@ -476,13 +487,14 @@ like so: >>> lollipop = nx.lollipop_graph(10, 20) 4. Using a stochastic graph generator, e.g, +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. autosummary:: - erdos_renyi_graph - watts_strogatz_graph - barabasi_albert_graph - random_lobster + ~networkx.generators.random_graphs.erdos_renyi_graph + ~networkx.generators.random_graphs.watts_strogatz_graph + ~networkx.generators.random_graphs.barabasi_albert_graph + ~networkx.generators.random_graphs.random_lobster like so: @@ -493,8 +505,11 @@ like so: >>> ba = nx.barabasi_albert_graph(100, 5) >>> red = nx.random_lobster(100, 0.9, 0.9) -5. Reading a graph stored in a file using common graph formats, - such as edge lists, adjacency lists, GML, GraphML, pickle, LEDA and others. +5. Reading a graph stored in a file using common graph formats +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +NetworkX supports many popular formats, such as edge lists, adjacency lists, +GML, GraphML, pickle, LEDA and others. .. nbplot:: @@ -539,8 +554,8 @@ Drawing graphs NetworkX is not primarily a graph drawing package but basic drawing with Matplotlib as well as an interface to use the open source Graphviz software -package are included. These are part of the ``networkx.drawing`` module and will -be imported if possible. +package are included. These are part of the :doc:`networkx.drawing <reference/drawing>` +module and will be imported if possible. First import Matplotlib's plot interface (pylab works too) @@ -548,7 +563,8 @@ First import Matplotlib's plot interface (pylab works too) >>> import matplotlib.pyplot as plt -To test if the import of ``networkx.drawing`` was successful draw ``G`` using one of +To test if the import of `~networkx.drawing.nx_pylab` was successful draw ``G`` +using one of .. nbplot:: @@ -583,7 +599,7 @@ command if you are not using matplotlib in interactive mode (see >>> nx.draw_shell(G, nlist=[range(5,10), range(5)], **options) You can find additional options via :func:`~drawing.nx_pylab.draw_networkx` and -layouts via :mod:`layout <networkx.drawing.layout>`. +layouts via the :mod:`layout module<networkx.drawing.layout>`. You can use multiple shells with :func:`~drawing.nx_pylab.draw_shell`. .. nbplot:: @@ -597,10 +613,11 @@ To save drawings to a file, use, for example >>> nx.draw(G) >>> plt.savefig("path.png") -writes to the file ``path.png`` in the local directory. If Graphviz and +This function writes to the file ``path.png`` in the local directory. If Graphviz and PyGraphviz or pydot, are available on your system, you can also use -``nx_agraph.graphviz_layout(G)`` or ``nx_pydot.graphviz_layout(G)`` to get the -node positions, or write the graph in dot format for further processing. +`networkx.drawing.nx_agraph.graphviz_layout` or +`networkx.drawing.nx_pydot.graphviz_layout` to get the node positions, or write +the graph in dot format for further processing. >>> from networkx.drawing.nx_pydot import write_dot >>> pos = nx.nx_agraph.graphviz_layout(G) diff --git a/networkx/classes/reportviews.py b/networkx/classes/reportviews.py index d8ae60d8..06d8dfde 100644 --- a/networkx/classes/reportviews.py +++ b/networkx/classes/reportviews.py @@ -207,6 +207,67 @@ class NodeView(Mapping, Set): return NodeDataView(self._nodes, data, default) def data(self, data=True, default=None): + """ + Return a read-only view of node data. + + Parameters + ---------- + data : bool or node data key, default=True + If ``data=True`` (the default), return a `NodeDataView` object that + maps each node to *all* of its attributes. `data` may also be an + arbitrary key, in which case the `NodeDataView` maps each node to + the value for the keyed attribute. In this case, if a node does + not have the `data` attribute, the `default` value is used. + default : object, default=None + The value used when a node does not have a specific attribute. + + Returns + ------- + NodeDataView + The layout of the returned NodeDataView depends on the value of the + `data` parameter. + + Notes + ----- + If ``data=False``, returns a `NodeView` object without data. + + See Also + -------- + NodeDataView + + Examples + -------- + >>> G = nx.Graph() + >>> G.add_nodes_from([ + ... (0, {"color": "red", "weight": 10}), + ... (1, {"color": "blue"}), + ... (2, {"color": "yellow", "weight": 2}) + ... ]) + + Accessing node data with ``data=True`` (the default) returns a + NodeDataView mapping each node to all of its attributes: + + >>> G.nodes.data() + NodeDataView({0: {'color': 'red', 'weight': 10}, 1: {'color': 'blue'}, 2: {'color': 'yellow', 'weight': 2}}) + + If `data` represents a key in the node attribute dict, a NodeDataView mapping + the nodes to the value for that specific key is returned: + + >>> G.nodes.data("color") + NodeDataView({0: 'red', 1: 'blue', 2: 'yellow'}, data='color') + + If a specific key is not found in an attribute dict, the value specified + by `default` is returned: + + >>> G.nodes.data("weight", default=-999) + NodeDataView({0: 10, 1: -999, 2: 2}, data='weight') + + Note that there is no check that the `data` key is in any of the + node attribute dictionaries: + + >>> G.nodes.data("height") + NodeDataView({0: None, 1: None, 2: None}, data='height') + """ if data is False: return self return NodeDataView(self._nodes, data, default) @@ -1038,6 +1099,79 @@ class OutEdgeView(Set, Mapping): return self.dataview(self, nbunch, data, default) def data(self, data=True, default=None, nbunch=None): + """ + Return a read-only view of edge data. + + Parameters + ---------- + data : bool or edge attribute key + If ``data=True``, then the data view maps each edge to a dictionary + containing all of its attributes. If `data` is a key in the edge + dictionary, then the data view maps each edge to its value for + the keyed attribute. In this case, if the edge doesn't have the + attribute, the `default` value is returned. + default : object, default=None + The value used when an edge does not have a specific attribute + nbunch : container of nodes, optional (default=None) + Allows restriction to edges only involving certain nodes. All edges + are considered by default. + + Returns + ------- + dataview + Returns an `EdgeDataView` for undirected Graphs, `OutEdgeDataView` + for DiGraphs, `MultiEdgeDataView` for MultiGraphs and + `OutMultiEdgeDataView` for MultiDiGraphs. + + Notes + ----- + If ``data=False``, returns an `EdgeView` without any edge data. + + See Also + -------- + EdgeDataView + OutEdgeDataView + MultiEdgeDataView + OutMultiEdgeDataView + + Examples + -------- + >>> G = nx.Graph() + >>> G.add_edges_from([ + ... (0, 1, {"dist": 3, "capacity": 20}), + ... (1, 2, {"dist": 4}), + ... (2, 0, {"dist": 5}) + ... ]) + + Accessing edge data with ``data=True`` (the default) returns an + edge data view object listing each edge with all of its attributes: + + >>> G.edges.data() + EdgeDataView([(0, 1, {'dist': 3, 'capacity': 20}), (0, 2, {'dist': 5}), (1, 2, {'dist': 4})]) + + If `data` represents a key in the edge attribute dict, a dataview listing + each edge with its value for that specific key is returned: + + >>> G.edges.data("dist") + EdgeDataView([(0, 1, 3), (0, 2, 5), (1, 2, 4)]) + + `nbunch` can be used to limit the edges: + + >>> G.edges.data("dist", nbunch=[0]) + EdgeDataView([(0, 1, 3), (0, 2, 5)]) + + If a specific key is not found in an edge attribute dict, the value + specified by `default` is used: + + >>> G.edges.data("capacity") + EdgeDataView([(0, 1, 20), (0, 2, None), (1, 2, None)]) + + Note that there is no check that the `data` key is present in any of + the edge attribute dictionaries: + + >>> G.edges.data("speed") + EdgeDataView([(0, 1, None), (0, 2, None), (1, 2, None)]) + """ if nbunch is None and data is False: return self return self.dataview(self, nbunch, data, default) |