diff --git a/libpysal/graph/base.py b/libpysal/graph/base.py index bac254018..821806414 100644 --- a/libpysal/graph/base.py +++ b/libpysal/graph/base.py @@ -995,9 +995,13 @@ def isolates(self): pandas.Index Index with a subset of observations that do not have any neighbor """ - nulls = self._adjacency[self._adjacency == 0].reset_index(level=1) + nulls = self._adjacency[self._adjacency == 0] # since not all zeros are necessarily isolates, do the focal == neighbor check - return nulls[nulls.index == nulls.neighbor].index.unique() + return ( + nulls[nulls.index.codes[0] == nulls.index.codes[1]] + .index.get_level_values(0) + .unique() + ) @cached_property def unique_ids(self): @@ -1399,6 +1403,22 @@ 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 + subset of Graph with zero-weight edges eliminated + """ + # get a mask for isolates + isolates = self._adjacency.index.codes[0] == self._adjacency.index.codes[1] + # substract isolates from mask of zeros + zeros = (self._adjacency == 0) != isolates + return Graph(self._adjacency[~zeros], 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 2dca9b048..3b755abf7 100644 --- a/libpysal/graph/tests/test_base.py +++ b/libpysal/graph/tests/test_base.py @@ -942,6 +942,14 @@ def test_component_labels(self): expected, nybb.component_labels, check_dtype=False ) + def test_eliminate_zeros(self): + adj = self.adjacency_str_binary.copy() + adj["Bronx", "Queens"] = 0 + adj["Queens", "Manhattan"] = 0 + with_zero = graph.Graph(adj) + expected = adj.drop([("Bronx", "Queens"), ("Queens", "Manhattan")]) + pd.testing.assert_series_equal(with_zero.eliminate_zeros()._adjacency, expected) + def test_subgraph(self): knn = graph.Graph.build_knn(self.nybb.set_geometry(self.nybb.centroid), k=2) sub = knn.subgraph(["Staten Island", "Bronx", "Brooklyn"])