libpysal.graph.Graph¶
- class libpysal.graph.Graph(adjacency, transformation='O')[source]¶
Graph class encoding spatial weights matrices
The
Graphis currently experimental and its API is incomplete and unstable.- __init__(adjacency, transformation='O')[source]¶
Weights base class based on adjacency list
It is recommenced to use one of the
from_*orbuild_*constructors rather than invoking__init__directly.Each observation needs to be present in the focal, at least as a self-loop with a weight 0.
- Parameters:
- adjacency
pandas.Series A MultiIndexed pandas.Series with
"focal"and"neigbor"levels encoding adjacency, and values encoding weights. By convention, isolates are encoded as self-loops with a weight 0.- transformation
python:str,default“O” weights transformation used to produce the table.
O – Original
B – Binary
R – Row-standardization (global sum \(=n\))
D – Double-standardization (global sum \(=1\))
V – Variance stabilizing
- adjacency
Methods
__init__(adjacency[, transformation])Weights base class based on adjacency list
asymmetry([intrinsic])Asymmetry check.
build_block_contiguity(regimes)Generate Graph from block contiguity (regime neighbors)
build_contiguity(geometry[, rook, ...])Generate Graph from geometry based on contiguity
build_distance_band(data, threshold[, ...])Generate Graph from geometry based on a distance band
build_fuzzy_contiguity(geometry[, ...])Generate Graph from fuzzy contiguity
build_kernel(data[, kernel, k, bandwidth, ...])Generate Graph from geometry data based on a kernel function
build_knn(data, k[, metric, p, coincident])Generate Graph from geometry data based on k-nearest neighbors search
build_triangulation(data[, method, ...])Generate Graph from geometry based on triangulation
copy([deep])Make a copy of this Graph's adjacency table and transformation
difference(right)Provide the set difference between the graph on the left and the graph on the right.
equals(right)Check that two graphs are identical.
explore(gdf[, focal, nodes, color, ...])Plot graph as an interactive Folium Map
from_W(w)Create an experimental Graph from libpysal.weights.W object
from_adjacency(adjacency[, focal_col, ...])Create a Graph from a pandas DataFrame formatted as an adjacency list
from_arrays(focal_ids, neighbor_ids, weight)Generate Graph from arrays of indices and weights of the same length
from_dicts(neighbors[, weights])Generate Graph from dictionaries of neighbors and weights
from_sparse(sparse[, ids])Convert a
scipy.sparsearray to a PySALGraphobject.from_weights_dict(weights_dict)Generate Graph from a dict of dicts
higher_order([k, shortest_path, diagonal, ...])Contiguity weights object of order \(k\).
intersection(right)Returns a binary Graph, that includes only those neighbor pairs that exist in both left and right.
intersects(right)Returns True if left and right share at least one link, irrespective of weights value.
isomorphic(right)Check that two graphs are isomorphic.
issubgraph(right)Return True if every link in the left Graph also occurs in the right Graph.
lag(y)Spatial lag operator
plot(gdf[, focal, nodes, color, edge_kws, ...])Plot edges and nodes of the Graph
symmetric_difference(right)Filter out links that are in both left and right Graph objects.
to_W()Convert Graph to a libpysal.weights.W object
Convert Graph to a
networkxgraph.to_parquet(path, **kwargs)Save Graph to a Apache Parquet
transform(transformation)Transformation of weights
union(right)Provide the union of two Graph objects, collecing all links that are in either graph.
Attributes
Return a copy of the adjacency list
Number of neighbors for each observation
Get component labels per observation
Index of observations with no neighbors
Number of observations.
Get a number of connected components
Number of observations.
Number of observations.
Get neighbors dictionary
Number of nonzero weights.
Percentage of nonzero weights.
Return a scipy.sparse array (COO)
Unique IDs used in the Graph
Get weights dictionary
- property adjacency¶
Return a copy of the adjacency list
- Returns:
pandas.SeriesUnderlying adjacency list
- asymmetry(intrinsic=True)[source]¶
Asymmetry check.
- Parameters:
- intrinsicbool,
optional Default is
True. Intrinsic symmetry is defined as:\[w_{i,j} == w_{j,i}\]If
intrinsicisFalsesymmetry is defined as:\[i \in N_j \ \& \ j \in N_i\]where \(N_j\) is the set of neighbors for \(j\), e.g.,
Truerequires equality of the weight to consider two links equal,Falserequires only a presence of a link with a non-zero weight.
- intrinsicbool,
- Returns:
pandas.SeriesA
Seriesof(i,j)pairs of asymmetries sorted ascending by the focal observation (index value), whereiis the focal andjis the neighbor. An emptySeriesis returned if no asymmetries are found.
- classmethod build_block_contiguity(regimes)[source]¶
Generate Graph from block contiguity (regime neighbors)
Block contiguity structures are relevant when defining neighbor relations based on membership in a regime. For example, all counties belonging to the same state could be defined as neighbors, in an analysis of all counties in the US.
- Parameters:
- regimeslist-like
list-like of regimes. If pandas.Series, its index is used to encode Graph. Otherwise a default RangeIndex is used.
- Returns:
Graphlibpysal.graph.Graph encoding block contiguity
- classmethod build_contiguity(geometry, rook=True, by_perimeter=False, strict=False)[source]¶
Generate Graph from geometry based on contiguity
Contiguity builder assumes that all geometries are forming a coverage, i.e. a non-overlapping mesh and neighbouring geometries share only points or segments of their exterior boundaries. In practice,
build_contiguityis capable of creating a Graph of partially overlapping geometries whenstrict=False, by_perimeter=False, but that would not strictly follow the definition of queen or rook contiguity.- Parameters:
- geometrynumpy:array_like
ofshapely.Geometryobjects Could be geopandas.GeoSeries or geopandas.GeoDataFrame, in which case the resulting Graph is indexed by the original index. If an array of shapely.Geometry objects is passed, Graph will assume a RangeIndex.
- rookbool,
optional Contiguity method. If True, two geometries are considered neighbours if they share at least one edge. If False, two geometries are considered neighbours if they share at least one vertex. By default True
- by_perimeterbool,
optional If True,
weightrepresents the length of the shared boundary between adjacent units, by default False. For row-standardized version of perimeter weights, useGraph.build_contiguity(gdf, by_perimeter=True).transform("r").- strictbool,
optional Use the strict topological method. If False, the contiguity is determined based on shared coordinates or coordinate sequences representing edges. This assumes geometry coverage that is topologically correct. This method is faster but can miss some relations. If True, the contiguity is determined based on geometric relations that do not require precise topology. This method is slower but will result in correct contiguity even if the topology of geometries is not optimal. By default False.
- geometrynumpy:array_like
- Returns:
Graphlibpysal.graph.Graph encoding contiguity weights
- classmethod build_distance_band(data, threshold, binary=True, alpha=-1.0, kernel=None, bandwidth=None)[source]¶
Generate Graph from geometry based on a distance band
- Parameters:
- data
numpy.ndarray,geopandas.GeoSeries,geopandas.GeoDataFrame geometries containing locations to compute the delaunay triangulation. If a geopandas object with Point geometry is provided, the .geometry attribute is used. If a numpy.ndarray with shapely geometry is used, then the coordinates are extracted and used. If a numpy.ndarray of a shape (2,n) is used, it is assumed to contain x, y coordinates.
- threshold
python:float distance band
- binarybool,
optional If True \(w_{ij}=1\) if \(d_{i,j}<=threshold\), otherwise \(w_{i,j}=0\). If False \(wij=dij^{alpha}\), by default True.
- alpha
python:float,optional distance decay parameter for weight (default -1.0) if alpha is positive the weights will not decline with distance. Ignored if
binary=Trueorkernelis not None.- kernel
python:str,optional kernel function to use in order to weight the output graph. See
Graph.build_kernel()for details. Ignored ifbinary=True.- bandwidth
python:float(default:python:None) distance to use in the kernel computation. Should be on the same scale as the input coordinates. Ignored if
binary=Trueorkernel=None.
- data
- Returns:
Graphlibpysal.graph.Graph encoding distance band weights
- classmethod build_fuzzy_contiguity(geometry, tolerance=None, buffer=None, predicate='intersects')[source]¶
Generate Graph from fuzzy contiguity
Fuzzy contiguity relaxes the notion of contiguity neighbors for the case of geometry collections that violate the condition of planar enforcement. It handles three types of conditions present in such collections that would result in missing links when using the regular contiguity methods.
The first are edges for nearby polygons that should be shared, but are digitized separately for the individual polygons and the resulting edges do not coincide, but instead the edges intersect. This case can also be covered by
build_contigutywith thestrict=Falseparameter.The second case is similar to the first, only the resultant edges do not intersect but are “close”. The optional buffering of geometry then closes the gaps between the polygons and a resulting intersection is encoded as a link.
The final case arises when one polygon is “inside” a second polygon but is not encoded to represent a hole in the containing polygon.
It is also possible to create a contiguity based on a custom spatial predicate.
- Parameters:
- geomsnumpy:array_like
ofshapely.Geometryobjects Could be geopandas.GeoSeries or geopandas.GeoDataFrame, in which case the resulting Graph is indexed by the original index. If an array of shapely.Geometry objects is passed, Graph will assume a RangeIndex.
- tolerance
python:float,optional The percentage of the length of the minimum side of the bounding rectangle for the
geomsto use in determining the buffering distance. Eithertoleranceorbuffermay be specified but not both. By default None.- buffer
python:float,optional Exact buffering distance in the units of
geoms.crs. Eithertoleranceorbuffermay be specified but not both. By default None.- predicate
python:str,optional The predicate to use for determination of neighbors. Default is ‘intersects’. If None is passed, neighbours are determined based on the intersection of bounding boxes. See the documentation of
geopandas.GeoSeries.sindex.queryfor allowed predicates.
- geomsnumpy:array_like
- Returns:
Graphlibpysal.graph.Graph encoding fuzzy contiguity
- classmethod build_kernel(data, kernel='gaussian', k=None, bandwidth=None, metric='euclidean', p=2, coincident='raise')[source]¶
Generate Graph from geometry data based on a kernel function
- Parameters:
- data
numpy.ndarray,geopandas.GeoSeries,geopandas.GeoDataFrame geometries over which to compute a kernel. If a geopandas object with Point geoemtry is provided, the .geometry attribute is used. If a numpy.ndarray with shapely geoemtry is used, then the coordinates are extracted and used. If a numpy.ndarray of a shape (2,n) is used, it is assumed to contain x, y coordinates. If metric=”precomputed”, data is assumed to contain a precomputed distance metric.
- kernel
python:strorpython:callable()(default: ‘gaussian’) kernel function to apply over the distance matrix computed by metric. The following kernels are supported:
"triangular":"parabolic":"gaussian":"bisquare":"cosine":'boxcar'/discrete: all distances less than bandwidth are 1, and all other distances are 0"identity"/None : do nothing, weight similarity based on raw distancecallable: a user-defined function that takes the distance vector and the bandwidth and returns the kernel: kernel(distances, bandwidth)
- k
python:int(default:python:None) number of nearest neighbors used to truncate the kernel. This is assumed to be constant across samples. If None, no truncation is conduted.
- bandwidth
python:float(default:python:None) distance to use in the kernel computation. Should be on the same scale as the input coordinates.
- metric
python:strorpython:callable()(default: ‘euclidean’) distance function to apply over the input coordinates. Supported options depend on whether or not scikit-learn is installed. If so, then any distance function supported by scikit-learn is supported here. Otherwise, only euclidean, minkowski, and manhattan/cityblock distances are admitted.
- p
python:int(default: 2) parameter for minkowski metric, ignored if metric != “minkowski”.
- coincident: str, optional (default “raise”)
Method for handling coincident points when
kis not None. Options are'raise'(raising an exception when coincident points are present),'jitter'(randomly displace coincident points to produce uniqueness), &'clique'(induce fully-connected sub cliques for coincident points).
- data
- Returns:
Graphlibpysal.graph.Graph encoding kernel weights
- classmethod build_knn(data, k, metric='euclidean', p=2, coincident='raise')[source]¶
Generate Graph from geometry data based on k-nearest neighbors search
- Parameters:
- data
numpy.ndarray,geopandas.GeoSeries,geopandas.GeoDataFrame geometries over which to compute a kernel. If a geopandas object with Point geoemtry is provided, the .geometry attribute is used. If a numpy.ndarray with shapely geoemtry is used, then the coordinates are extracted and used. If a numpy.ndarray of a shape (2,n) is used, it is assumed to contain x, y coordinates.
- k
python:int number of nearest neighbors.
- metric
python:strorpython:callable()(default: ‘euclidean’) distance function to apply over the input coordinates. Supported options depend on whether or not scikit-learn is installed. If so, then any distance function supported by scikit-learn is supported here. Otherwise, only euclidean, minkowski, and manhattan/cityblock distances are admitted.
- p
python:int(default: 2) parameter for minkowski metric, ignored if metric != “minkowski”.
- coincident: str, optional (default “raise”)
Method for handling coincident points. Options include
'raise'(raising an exception when coincident points are present),'jitter'(randomly displace coincident points to produce uniqueness), &'clique'(induce fully-connected sub cliques for coincident points).
- data
- Returns:
Graphlibpysal.graph.Graph encoding KNN weights
- classmethod build_triangulation(data, method='delaunay', bandwidth=inf, kernel='boxcar', clip='extent', rook=True, coincident='raise')[source]¶
Generate Graph from geometry based on triangulation
- Parameters:
- data
numpy.ndarray,geopandas.GeoSeries,geopandas.GeoDataFrame geometries containing locations to compute the delaunay triangulation. If a geopandas object with Point geoemtry is provided, the .geometry attribute is used. If a numpy.ndarray with shapely geoemtry is used, then the coordinates are extracted and used. If a numpy.ndarray of a shape (2,n) is used, it is assumed to contain x, y coordinates.
- method
python:str, (default“delaunay”) method of extracting the weights from triangulation. Supports:
"delaunay""gabriel""relative_neighborhood""voronoi"
- bandwidth
python:float,optional distance to use in the kernel computation. Should be on the same scale as the input coordinates, by default numpy.inf
- kernel
python:str,optional kernel function to use in order to weight the output graph. See
Graph.build_kernel()for details. By default “boxcar”- clip
python:str(default: ‘bbox’) Clipping method when
method="voronoi". Ignored otherwise. Default is'extent'. Options are as follows.'none'/None: No clip is applied. Voronoi cells may be arbitrarily larger that the source map. Note that this may lead to cells that are many orders of magnitude larger in extent than the original map. Not recommended.'bbox'/'extent'/'bounding box': Clip the voronoi cells to the bounding box of the input points.'chull/'convex hull': Clip the voronoi cells to the convex hull of the input points.'ashape'/'ahull': Clip the voronoi cells to the tightest hull that contains all points (e.g. the smallest alphashape, usinglibpysal.cg.alpha_shape_auto()).shapely.Polygon: Clip to an arbitrary Polygon.
- rookbool,
optional Contiguity method when
method="voronoi". Ignored otherwise. If True, two geometries are considered neighbours if they share at least one edge. If False, two geometries are considered neighbours if they share at least one vertex. By default True- coincident: str, optional (default “raise”)
Method for handling coincident points. Options include
'raise'(raising an exception when coincident points are present),'jitter'(randomly displace coincident points to produce uniqueness), &'clique'(induce fully-connected sub cliques for coincident points).
- data
- Returns:
Graphlibpysal.graph.Graph encoding triangulation weights
- property cardinalities¶
Number of neighbors for each observation
- Returns:
pandas.SeriesSeries with a number of neighbors per each observation
- property component_labels¶
Get component labels per observation
- Returns:
numpy.arrayArray of component labels
- copy(deep=True)[source]¶
Make a copy of this Graph’s adjacency table and transformation
- Parameters:
- deepbool,
optional Make a deep copy of the adjacency table, by default True
- deepbool,
- Returns:
Graphlibpysal.graph.Graph as a copy of the original
- explore(gdf, focal=None, nodes=True, color='black', edge_kws=None, node_kws=None, focal_kws=None, m=None, **kwargs)[source]¶
Plot graph as an interactive Folium Map
- Parameters:
- gdf
geopandas.GeoDataFrame geodataframe used to instantiate to Graph
- focal
python:list,optional subset of focal observations to plot in the map, by default None. If none, all relationships are plotted
- nodesbool,
optional whether to display observations as nodes in the map, by default True
- color
python:str,optional color applied to nodes and edges, by default “black”
- edge_kws
python:dict,optional additional keyword arguments passed to geopandas explore function when plotting edges, by default None
- node_kws
python:dict,optional additional keyword arguments passed to geopandas explore function when plotting nodes, by default None
- focal_kws
python:dict,optional additional keyword arguments passed to geopandas explore function when plotting focal observations, by default None. Only applicable when passing a subset of nodes with the focal argument
- m
Folilum.Map,optional folium map objecto to plot on top of, by default None
- **kwargs
python:dict,optional additional keyword arguments are passed directly to geopandas.explore, when
m=Noneby default None
- gdf
- Returns:
folium.Mapfolium map
- classmethod from_W(w)[source]¶
Create an experimental Graph from libpysal.weights.W object
- Parameters:
- Returns:
Graphlibpysal.graph.Graph from W
- classmethod from_adjacency(adjacency, focal_col='focal', neighbor_col='neighbor', weight_col='weight')[source]¶
Create a Graph from a pandas DataFrame formatted as an adjacency list
- Parameters:
- adjacency
pandas.DataFrame a dataframe formatted as an ajacency list. Should have columns “focal”, “neighbor”, and “weight”, or columns that can be mapped to these (e.g. origin, destination, cost)
- focal
python:str,optional name of column holding focal/origin index, by default ‘focal’
- neighbor
python:str,optional name of column holding neighbor/destination index, by default ‘neighbor’
- weight
python:str,optional name of column holding weight values, by default ‘weight’
- adjacency
- Returns:
Graphlibpysal.graph.Graph
- classmethod from_arrays(focal_ids, neighbor_ids, weight)[source]¶
Generate Graph from arrays of indices and weights of the same length
The arrays needs to be sorted in a way ensuring that focal_ids.unique() is equal to the index of original observations from which the Graph is being built
- Parameters:
- focal_indexnumpy:array_like
focal indices
- neighbor_indexnumpy:array_like
neighbor indices
- weightnumpy:array_like
weights
- Returns:
Graphlibpysal.graph.Graph based on arrays
- classmethod from_dicts(neighbors, weights=None)[source]¶
Generate Graph from dictionaries of neighbors and weights
- Parameters:
- neighbors
python:dict dictionary of neighbors with the
{focal: [neighbor1, neighbor2]}structure- weights
python:dict,optional dictionary of neighbors with the
{focal: [weight1, weight2]}structure. If None, assumes binary weights.
- neighbors
- Returns:
Graphlibpysal.graph.Graph based on dictionaries
- classmethod from_sparse(sparse, ids=None)[source]¶
Convert a
scipy.sparsearray to a PySALGraphobject.- Parameters:
- sparse
scipy.sparsearray sparse representation of a graph
- idslist-like,
defaultpython:None list-like of ids for geometries that is mappable to positions from sparse. If None, the positions are used as labels.
- sparse
- Returns:
Graphlibpysal.graph.Graph based on sparse
- classmethod from_weights_dict(weights_dict)[source]¶
Generate Graph from a dict of dicts
- Parameters:
- weights_dict
dictionaryofdictionaries weights dictionary with the
{focal: {neighbor: weight}}structure.
- weights_dict
- Returns:
Graphlibpysal.graph.Graph based on weights dictionary of dictionaries
- higher_order(k=2, shortest_path=True, diagonal=False, lower_order=False)[source]¶
Contiguity weights object of order \(k\).
Proper higher order neighbors are returned such that \(i\) and \(j\) are \(k\)-order neighbors if the shortest path from \(i-j\) is of length \(k\).
- Parameters:
- k
python:int,optional Order of contiguity. By default 2.
- shortest_pathbool,
optional If True, \(i,j\) and \(k\)-order neighbors if the shortest path for \(i,j\) is \(k\). If False, \(i,j\) are k-order neighbors if there is a path from \(i,j\) of length \(k\). By default True.
- diagonalbool,
optional If True, keep \(k\)-order (\(i,j\)) joins when \(i==j\). If False, remove \(k\)-order (\(i,j\)) joins when \(i==j\). By default False.
- lower_orderbool,
optional If True, include lower order contiguities. If False return only weights of order \(k\). By default False.
- k
- Returns:
Graphhigher order weights
- property isolates¶
Index of observations with no neighbors
Isolates are encoded as a self-loop with the weight == 0 in the adjacency table.
- Returns:
pandas.IndexIndex with a subset of observations that do not have any neighbor
- lag(y)[source]¶
Spatial lag operator
If weights are row standardized, returns the mean of each observation’s neighbors; if not, returns the weighted sum of each observation’s neighbors.
- Parameters:
- ynumpy:array_like
array-like (N,) shape where N is equal to number of observations in self.
- Returns:
numpy.ndarrayarray of numeric values for the spatial lag
- property n¶
Number of observations.
- property n_components¶
Get a number of connected components
- Returns:
python:intnumber of components
- property n_edges¶
Number of observations.
- property n_nodes¶
Number of observations.
- property neighbors¶
Get neighbors dictionary
- Returns:
python:dictdict of tuples representing neighbors
Notes
It is recommended to work directly with
Graph.adjacency()rather than using theGraph.neighbors().
- property nonzero¶
Number of nonzero weights.
- property pct_nonzero¶
Percentage of nonzero weights.
- plot(gdf, focal=None, nodes=True, color='k', edge_kws=None, node_kws=None, focal_kws=None, ax=None, figsize=None, limit_extent=False)[source]¶
Plot edges and nodes of the Graph
Creates a
maptlotlibplot based on the topology stored in the Graph and spatial location defined ingdf.- Parameters:
- gdf
geopandas.GeoDataFrame Geometries indexed using the same index as Graph. Geometry types other than points are converted to centroids encoding start and end point of Graph edges.
- focal
hashable| numpy:array_like[hashable] |python:None,optional ID or an array-like of IDs of focal geometries whose weights shall be plotted. If None, all weights from all focal geometries are plotted. By default None
- nodesbool,
optional Plot nodes as points, by default True
- color
python:str,optional The color of all objects, by default “k”
- edge_kws
python:dict,optional Keyword arguments dictionary to send to
LineCollection, which provides fine-grained control over the aesthetics of the edges in the plot. By default None- node_kws
python:dict,optional Keyword arguments dictionary to send to
ax.scatter, which provides fine-grained control over the aesthetics of the nodes in the plot. By default None- focal_kws
python:dict,optional Keyword arguments dictionary to send to
ax.scatter, which provides fine-grained control over the aesthetics of the focal nodes in the plot on top of genericnode_kws. Values ofnode_kwsare updated fromfocal_kws. Ignored iffocal=None. By default None- ax
matplotlib.axes.Axes,optional Axis on which to plot the weights. If None, a new figure and axis are created. By default None
- figsize
python:tuple,optional figsize used to create a new axis. By default None
- limit_extentbool,
optional limit the extent of the axis to the extent of the plotted graph, by default False
- gdf
- Returns:
matplotlib.axes.AxesAxis with the resulting plot
Notes
If you’d like to overlay the actual geometries from the
geopandas.GeoDataFrame, create an axis by plotting theGeoDataFrameand plot the Graph on top.ax = gdf.plot() gdf_graph.plot(gdf, ax=ax)
- property sparse¶
Return a scipy.sparse array (COO)
- Returns:
scipy.sparse.COOsparse representation of the adjacency
- to_W()[source]¶
Convert Graph to a libpysal.weights.W object
- Returns:
libpysal.weights.Wrepresentation of graph as a weights.W object
- to_networkx()[source]¶
Convert Graph to a
networkxgraph.If Graph is symmetric, returns
nx.Graph, otherwise returns anx.DiGraph.- Returns:
networkx.Graph|networkx.DiGraphRepresentation of libpysal Graph as networkx graph
- to_parquet(path, **kwargs)[source]¶
Save Graph to a Apache Parquet
Graph is serialized to the Apache Parquet using the underlying adjacency object stored as a Parquet table and custom metadata containing transformation.
Requires pyarrow package.
- Parameters:
- path
python:str|pyarrow.NativeFile path or any stream supported by pyarrow
- **kwargs
additional keyword arguments passed to pyarrow.parquet.write_table
- path
See also
read_parquet
- transform(transformation)[source]¶
Transformation of weights
- Parameters:
- transformation
python:str Transformation method. The following are valid transformations.
B – Binary
R – Row-standardization (global sum \(=n\))
D – Double-standardization (global sum \(=1\))
V – Variance stabilizing
- transformation
- Returns:
Graphtransformed weights
- Raises:
ValueErrorValue error for unsupported transformation
- property unique_ids¶
Unique IDs used in the Graph
- property weights¶
Get weights dictionary
- Returns:
python:dictdict of tuples representing weights
Notes
It is recommended to work directly with
Graph.adjacency()rather than using theGraph.weights().