Skip to content

Commit

Permalink
ENH: neighbor_distance using Graph and new API (pysal#555)
Browse files Browse the repository at this point in the history
  • Loading branch information
martinfleis authored Mar 6, 2024
1 parent 3a76ad6 commit 1921627
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 2 deletions.
35 changes: 33 additions & 2 deletions momepy/functional/_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from packaging.version import Version
from pandas import Series

__all__ = ["orientation", "shared_walls", "alignment"]
__all__ = ["orientation", "shared_walls", "alignment", "neighbor_distance"]

GPD_GE_013 = Version(gpd.__version__) >= Version("0.13.0")

Expand Down Expand Up @@ -98,7 +98,7 @@ def alignment(orientation: Series, graph: Graph) -> Series:
.. math::
\\frac{1}{n}\\sum_{i=1}^n dev_i=\\frac{dev_1+dev_2+\\cdots+dev_n}{n}
Takes orientation of adjacent elemtents defined in ``graph`` and calculates the
Takes orientation of adjacent elements defined in ``graph`` and calculates the
mean deviation.
Notes
Expand All @@ -121,3 +121,34 @@ def alignment(orientation: Series, graph: Graph) -> Series:
orientation_expanded = orientation.loc[graph._adjacency.index.get_level_values(1)]
orientation_expanded.index = graph._adjacency.index.get_level_values(0)
return (orientation_expanded - orientation).abs().groupby(level=0).mean()


def neighbor_distance(geometry: GeoDataFrame | GeoSeries, graph: Graph) -> Series:
"""Calculate the mean distance to adjacent elements.
Takes geometry of adjacent elements defined in ``graph`` and calculates the
mean distance.
Notes
-----
The index of ``geometry`` must match the index along which the ``graph`` is
built.
Parameters
----------
geometry : GeoDataFrame | GeoSeries
A GeoDataFrame or GeoSeries containing geometries to analyse.
graph : libpysal.graph.Graph
Graph representing spatial relationships between elements.
Returns
-------
Series
"""
geoms = geometry.geometry.loc[graph._adjacency.index.get_level_values(1)]
geoms.index = graph._adjacency.index.get_level_values(0)
mean_distance = (
(geoms.distance(geometry.geometry, align=True)).groupby(level=0).mean()
)
mean_distance.loc[graph.isolates] = np.nan
return mean_distance
17 changes: 17 additions & 0 deletions momepy/functional/tests/test_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,16 @@ def test_alignment(self):
r = mm.alignment(orientation, self.graph)
assert_result(r, expected, self.df_buildings)

def test_neighbor_distance(self):
expected = {
"mean": 14.254601392635818,
"sum": 2052.662600539558,
"min": 2.0153493186952085,
"max": 42.164831456311475,
}
r = mm.neighbor_distance(self.df_buildings, self.graph)
assert_result(r, expected, self.df_buildings)


class TestEquality:
def setup_method(self):
Expand All @@ -74,3 +84,10 @@ def test_alignment(self):
verbose=False,
).series
assert_series_equal(new, old, check_names=False, check_index=False)

def test_neighbor_distance(self):
new = mm.neighbor_distance(self.df_buildings, self.graph)
old = mm.NeighborDistance(
self.df_buildings.reset_index(), self.graph.to_W(), "uID", verbose=False
).series
assert_series_equal(new, old, check_names=False, check_index=False)

0 comments on commit 1921627

Please # to comment.