huff 1.1.2__py3-none-any.whl → 1.3.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- huff/gistools.py +123 -3
- huff/models.py +925 -134
- huff/ors.py +16 -16
- huff/osm.py +207 -0
- huff/tests/data/Wieland2015.xlsx +0 -0
- huff/tests/tests_huff.py +146 -41
- {huff-1.1.2.dist-info → huff-1.3.0.dist-info}/METADATA +31 -11
- {huff-1.1.2.dist-info → huff-1.3.0.dist-info}/RECORD +10 -8
- {huff-1.1.2.dist-info → huff-1.3.0.dist-info}/WHEEL +0 -0
- {huff-1.1.2.dist-info → huff-1.3.0.dist-info}/top_level.txt +0 -0
huff/gistools.py
CHANGED
@@ -4,13 +4,15 @@
|
|
4
4
|
# Author: Thomas Wieland
|
5
5
|
# ORCID: 0000-0001-5168-9846
|
6
6
|
# mail: geowieland@googlemail.com
|
7
|
-
# Version: 1.
|
8
|
-
# Last update: 2025-05-
|
7
|
+
# Version: 1.3.0
|
8
|
+
# Last update: 2025-05-22 05:44
|
9
9
|
# Copyright (c) 2025 Thomas Wieland
|
10
10
|
#-----------------------------------------------------------------------
|
11
11
|
|
12
12
|
|
13
13
|
import geopandas as gp
|
14
|
+
import pandas as pd
|
15
|
+
from pandas.api.types import is_numeric_dtype
|
14
16
|
from math import pi, sin, cos, acos
|
15
17
|
|
16
18
|
|
@@ -60,6 +62,65 @@ def distance_matrix(
|
|
60
62
|
return matrix
|
61
63
|
|
62
64
|
|
65
|
+
def buffers(
|
66
|
+
point_gdf: gp.GeoDataFrame,
|
67
|
+
unique_id_col: str,
|
68
|
+
distances: list,
|
69
|
+
donut: bool = True,
|
70
|
+
save_output: bool = True,
|
71
|
+
output_filepath: str = "buffers.shp",
|
72
|
+
output_crs: str = "EPSG:4326"
|
73
|
+
):
|
74
|
+
|
75
|
+
all_buffers_gdf = gp.GeoDataFrame(columns=[unique_id_col, "segment", "geometry"])
|
76
|
+
|
77
|
+
for idx, row in point_gdf.iterrows():
|
78
|
+
|
79
|
+
point_buffers = []
|
80
|
+
|
81
|
+
for distance in distances:
|
82
|
+
|
83
|
+
point = row["geometry"]
|
84
|
+
point_buffer = point.buffer(distance)
|
85
|
+
|
86
|
+
point_buffer_gdf = gp.GeoDataFrame(
|
87
|
+
{
|
88
|
+
unique_id_col: row[unique_id_col],
|
89
|
+
"geometry": [point_buffer],
|
90
|
+
"segment": [distance]
|
91
|
+
},
|
92
|
+
crs=point_gdf.crs
|
93
|
+
)
|
94
|
+
|
95
|
+
point_buffers.append(point_buffer_gdf)
|
96
|
+
|
97
|
+
point_buffers_gdf = pd.concat(
|
98
|
+
point_buffers,
|
99
|
+
ignore_index = True
|
100
|
+
)
|
101
|
+
|
102
|
+
if donut:
|
103
|
+
point_buffers_gdf = overlay_difference(
|
104
|
+
polygon_gdf = point_buffers_gdf,
|
105
|
+
sort_col = "segment"
|
106
|
+
)
|
107
|
+
|
108
|
+
all_buffers_gdf = pd.concat(
|
109
|
+
[
|
110
|
+
all_buffers_gdf,
|
111
|
+
point_buffers_gdf
|
112
|
+
],
|
113
|
+
ignore_index = True)
|
114
|
+
|
115
|
+
all_buffers_gdf = all_buffers_gdf.to_crs(output_crs)
|
116
|
+
|
117
|
+
if save_output:
|
118
|
+
all_buffers_gdf.to_file(output_filepath)
|
119
|
+
print ("Saved as", output_filepath)
|
120
|
+
|
121
|
+
return all_buffers_gdf
|
122
|
+
|
123
|
+
|
63
124
|
def overlay_difference(
|
64
125
|
polygon_gdf: gp.GeoDataFrame,
|
65
126
|
sort_col: str = None,
|
@@ -74,6 +135,7 @@ def overlay_difference(
|
|
74
135
|
new_data = []
|
75
136
|
|
76
137
|
for i in range(len(polygon_gdf) - 1, 0, -1):
|
138
|
+
|
77
139
|
current_polygon = polygon_gdf.iloc[i].geometry
|
78
140
|
previous_polygon = polygon_gdf.iloc[i - 1].geometry
|
79
141
|
difference_polygon = current_polygon.difference(previous_polygon)
|
@@ -85,7 +147,9 @@ def overlay_difference(
|
|
85
147
|
new_data.append(polygon_gdf.iloc[i].drop("geometry"))
|
86
148
|
|
87
149
|
inner_most_polygon = polygon_gdf.iloc[0].geometry
|
150
|
+
|
88
151
|
if inner_most_polygon.is_valid:
|
152
|
+
|
89
153
|
new_geometries.append(inner_most_polygon)
|
90
154
|
new_data.append(polygon_gdf.iloc[0].drop("geometry"))
|
91
155
|
|
@@ -93,4 +157,60 @@ def overlay_difference(
|
|
93
157
|
new_data, geometry=new_geometries, crs=polygon_gdf.crs
|
94
158
|
)
|
95
159
|
|
96
|
-
return polygon_gdf_difference
|
160
|
+
return polygon_gdf_difference
|
161
|
+
|
162
|
+
|
163
|
+
def point_spatial_join(
|
164
|
+
polygon_gdf: gp.GeoDataFrame,
|
165
|
+
point_gdf: gp.GeoDataFrame,
|
166
|
+
join_type: str = "inner",
|
167
|
+
polygon_ref_cols: list = [],
|
168
|
+
point_stat_col: str = None
|
169
|
+
):
|
170
|
+
|
171
|
+
if polygon_gdf.crs != point_gdf.crs:
|
172
|
+
raise ValueError (f"Coordinate reference systems of polygon and point data do not match. Polygons: {str(polygon_gdf.crs)}, points: {str(point_gdf.crs)}")
|
173
|
+
|
174
|
+
if polygon_ref_cols != []:
|
175
|
+
for polygon_ref_col in polygon_ref_cols:
|
176
|
+
if polygon_ref_col not in polygon_gdf.columns:
|
177
|
+
raise KeyError (f"Column {polygon_ref_col} not in polygon data")
|
178
|
+
|
179
|
+
if point_stat_col is not None:
|
180
|
+
if point_stat_col not in point_gdf.columns:
|
181
|
+
raise KeyError (f"Column {point_stat_col} not in point data")
|
182
|
+
if not is_numeric_dtype(point_gdf[point_stat_col]):
|
183
|
+
raise TypeError (f"Column {point_stat_col} is not numeric")
|
184
|
+
|
185
|
+
shp_points_gdf_join = point_gdf.sjoin(
|
186
|
+
polygon_gdf,
|
187
|
+
how=join_type
|
188
|
+
)
|
189
|
+
|
190
|
+
spatial_join_stat = None
|
191
|
+
|
192
|
+
if polygon_ref_cols != [] and point_stat_col is not None:
|
193
|
+
shp_points_gdf_join_count = shp_points_gdf_join.groupby(polygon_ref_cols)[point_stat_col].count()
|
194
|
+
shp_points_gdf_join_sum = shp_points_gdf_join.groupby(polygon_ref_cols)[point_stat_col].sum()
|
195
|
+
shp_points_gdf_join_min = shp_points_gdf_join.groupby(polygon_ref_cols)[point_stat_col].min()
|
196
|
+
shp_points_gdf_join_max = shp_points_gdf_join.groupby(polygon_ref_cols)[point_stat_col].max()
|
197
|
+
shp_points_gdf_join_mean = shp_points_gdf_join.groupby(polygon_ref_cols)[point_stat_col].mean()
|
198
|
+
|
199
|
+
shp_points_gdf_join_count = shp_points_gdf_join_count.rename("count").to_frame()
|
200
|
+
shp_points_gdf_join_sum = shp_points_gdf_join_sum.rename("sum").to_frame()
|
201
|
+
shp_points_gdf_join_min = shp_points_gdf_join_min.rename("min").to_frame()
|
202
|
+
shp_points_gdf_join_max = shp_points_gdf_join_max.rename("max").to_frame()
|
203
|
+
shp_points_gdf_join_mean = shp_points_gdf_join_mean.rename("mean").to_frame()
|
204
|
+
spatial_join_stat = shp_points_gdf_join_count.join(
|
205
|
+
[
|
206
|
+
shp_points_gdf_join_sum,
|
207
|
+
shp_points_gdf_join_min,
|
208
|
+
shp_points_gdf_join_max,
|
209
|
+
shp_points_gdf_join_mean
|
210
|
+
]
|
211
|
+
)
|
212
|
+
|
213
|
+
return [
|
214
|
+
shp_points_gdf_join,
|
215
|
+
spatial_join_stat
|
216
|
+
]
|