From d02e70d043e4d82ced8a9e61c5e2e513d07b9103 Mon Sep 17 00:00:00 2001 From: Serge Rey Date: Mon, 16 Jan 2023 17:26:50 -0800 Subject: [PATCH 1/3] Handle set_index properly in to_adjlist --- libpysal/weights/weights.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libpysal/weights/weights.py b/libpysal/weights/weights.py index c71e40560..8cbbd58f5 100644 --- a/libpysal/weights/weights.py +++ b/libpysal/weights/weights.py @@ -432,6 +432,9 @@ def to_adjlist( links = [] focal_ix, neighbor_ix = self.sparse.nonzero() + idxs = np.array(list(self.neighbors.keys())) + focal_ix = idxs[focal_ix] + neighbor_ix = idxs[neighbor_ix] weights = self.sparse.data adjlist = pandas.DataFrame( {focal_col: focal_ix, neighbor_col: neighbor_ix, weight_col: weights} From 4cd9119e12853ff73231935addf793195f135c45 Mon Sep 17 00:00:00 2001 From: Serge Rey Date: Mon, 16 Jan 2023 20:01:34 -0800 Subject: [PATCH 2/3] Add option to sort/unsort return from to_adjlist --- libpysal/weights/tests/test_adjlist.py | 15 +++++++++++++++ libpysal/weights/weights.py | 9 ++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/libpysal/weights/tests/test_adjlist.py b/libpysal/weights/tests/test_adjlist.py index 48e70607a..913c9519a 100644 --- a/libpysal/weights/tests/test_adjlist.py +++ b/libpysal/weights/tests/test_adjlist.py @@ -145,3 +145,18 @@ def test_map(self): np.testing.assert_allclose( data, mapped["_".join(("subtract", name))].values ) + + def test_sort(self): + from libpysal import examples + from libpysal.weights import Rook + + us = geopandas.read_file(examples.get_path("us48.shp")) + w = Rook.from_dataframe(us.set_index("STATE_FIPS"), use_index=True) + unsorted_al = w.to_adjlist(sort_joins=False) + sorted_al = w.to_adjlist(sort_joins=True) + sv = ["01"] * 4 + sv.append("04") + sv = np.array(sv) + usv = np.array(["53", "53", "30", "30", "30"]) + np.testing.assert_array_equal(unsorted_al.focal.values[:5], usv) + np.testing.assert_array_equal(sorted_al.focal.values[:5], sv) diff --git a/libpysal/weights/weights.py b/libpysal/weights/weights.py index 8cbbd58f5..5f43eb36e 100644 --- a/libpysal/weights/weights.py +++ b/libpysal/weights/weights.py @@ -391,6 +391,7 @@ def to_adjlist( focal_col="focal", neighbor_col="neighbor", weight_col="weight", + sort_joins=False, ): """ Compute an adjacency list representation of a weights object. @@ -416,6 +417,10 @@ def to_adjlist( Name of the column in which to store "destination" node ids. weight_col : str Name of the column in which to store weight information. + sort_joins : bool + Whether or not to lexicographically sort the adjacency + list by (focal_col, neighbor_col). Default is False. + """ try: import pandas @@ -446,7 +451,9 @@ def to_adjlist( {focal_col: self.islands, neighbor_col: self.islands, weight_col: 0} ) adjlist = pandas.concat((adjlist, island_adjlist)).reset_index(drop=True) - return adjlist.sort_values([focal_col, neighbor_col]) + if sort_joins: + return adjlist.sort_values([focal_col, neighbor_col]) + return adjlist def to_networkx(self): """Convert a weights object to a ``networkx`` graph. From 7cca4e5505bd20ebd40362961ec25bead2de7950 Mon Sep 17 00:00:00 2001 From: eli knaap Date: Thu, 19 Jan 2023 16:07:42 -0800 Subject: [PATCH 3/3] Update libpysal/weights/tests/test_adjlist.py Co-authored-by: Martin Fleischmann --- libpysal/weights/tests/test_adjlist.py | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/libpysal/weights/tests/test_adjlist.py b/libpysal/weights/tests/test_adjlist.py index 913c9519a..f1cc08c86 100644 --- a/libpysal/weights/tests/test_adjlist.py +++ b/libpysal/weights/tests/test_adjlist.py @@ -160,3 +160,30 @@ def test_sort(self): usv = np.array(["53", "53", "30", "30", "30"]) np.testing.assert_array_equal(unsorted_al.focal.values[:5], usv) np.testing.assert_array_equal(sorted_al.focal.values[:5], sv) + + def test_ids(self): + df = geopandas.read_file(examples.get_path("columbus.dbf")).head() + df["my_id"] = range(3, len(df) + 3) + W = weights.Queen.from_dataframe(df, ids="my_id") + W_adj = W.to_adjlist(drop_islands=True) + for i in range(3, 8): + assert i in W_adj.focal + assert i in W_adj.neighbor + for i in W_adj.focal: + assert i in list(range(3, len(df) + 3)) + for i in W_adj.neighbor: + assert i in list(range(3, len(df) + 3)) + + def test_str_ids(self): + df = geopandas.read_file(examples.get_path("columbus.dbf")).head() + snakes = ["mamba", "boa", "python", "rattlesnake", "cobra"] + df["my_str_id"] = snakes + W = weights.Queen.from_dataframe(df, ids="my_str_id") + W_adj = W.to_adjlist(drop_islands=True) + for i in snakes: + (W_adj.focal == i).any() + (W_adj.neighbor == i).any() + for i in W_adj.focal: + assert i in snakes + for i in W_adj.neighbor: + assert i in snakes