diff --git a/libpysal/graph/base.py b/libpysal/graph/base.py index a52a23add..7bcb9eda4 100644 --- a/libpysal/graph/base.py +++ b/libpysal/graph/base.py @@ -1405,9 +1405,11 @@ def subgraph(self, ids): def eliminate_zeros(self): """Remove graph edges with zero weight + Eliminates edges with weight == 0 that do not encode an isolate. This is useful to clean-up edges that will make no effect in operations like :meth:`lag`. + Returns ------- Graph @@ -1419,6 +1421,40 @@ def eliminate_zeros(self): zeros = (self._adjacency == 0) != isolates return Graph(self._adjacency[~zeros], is_sorted=True) + def assign_self_weight(self, weight=1): + """Assign values to edges representing self-weight. + + The value for each ``focal == neighbor`` location in + the graph is set to ``weight``. + + Parameters + ---------- + weight : float | array-like + Defines the value(s) to which the weight representing the relationship with + itself should be set. If a constant is passed then each self-weight will get + this value (default is 1). An array of length ``Graph.n`` can be passed to + set explicit values to each self-weight (assumed to be in the same order as + original data). + + Returns + ------- + Graph + A new ``Graph`` with added self-weights. + """ + addition = pd.Series( + weight, + index=pd.MultiIndex.from_arrays( + [self.unique_ids, self.unique_ids], names=["focal", "neighbor"] + ), + name="weight", + ) + adj = ( + pd.concat([self.adjacency.drop(self.isolates), addition]) + .reindex(self.unique_ids, level=0) + .reindex(self.unique_ids, level=1) + ) + return Graph(adj, is_sorted=True) + def _arrange_arrays(heads, tails, weights, ids=None): """ diff --git a/libpysal/graph/tests/test_base.py b/libpysal/graph/tests/test_base.py index 3b755abf7..5d45dcc92 100644 --- a/libpysal/graph/tests/test_base.py +++ b/libpysal/graph/tests/test_base.py @@ -966,3 +966,19 @@ def test_subgraph(self): ), ) pd.testing.assert_series_equal(expected, sub._adjacency, check_dtype=False) + + def test_assign_self_weight(self): + contig = graph.Graph.build_contiguity(self.nybb) + diag = contig.assign_self_weight() + assert len(diag._adjacency) == 15 + assert diag._adjacency.sum() == 15 + + diag_array = contig.assign_self_weight([2, 3, 4, 5, 6]) + assert len(diag_array._adjacency) == 15 + assert diag_array._adjacency.sum() == 30 + + for i, val in enumerate(range(2, 7)): + assert ( + diag_array._adjacency[(contig.unique_ids[i], contig.unique_ids[i])] + == val + )