ssb-sgis 1.0.1__py3-none-any.whl → 1.0.3__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.
- sgis/__init__.py +107 -121
- sgis/exceptions.py +5 -3
- sgis/geopandas_tools/__init__.py +1 -0
- sgis/geopandas_tools/bounds.py +86 -47
- sgis/geopandas_tools/buffer_dissolve_explode.py +62 -39
- sgis/geopandas_tools/centerlines.py +53 -44
- sgis/geopandas_tools/cleaning.py +87 -104
- sgis/geopandas_tools/conversion.py +164 -107
- sgis/geopandas_tools/duplicates.py +33 -19
- sgis/geopandas_tools/general.py +84 -52
- sgis/geopandas_tools/geometry_types.py +24 -10
- sgis/geopandas_tools/neighbors.py +23 -11
- sgis/geopandas_tools/overlay.py +136 -53
- sgis/geopandas_tools/point_operations.py +11 -10
- sgis/geopandas_tools/polygon_operations.py +53 -61
- sgis/geopandas_tools/polygons_as_rings.py +121 -78
- sgis/geopandas_tools/sfilter.py +17 -17
- sgis/helpers.py +116 -58
- sgis/io/dapla_functions.py +32 -23
- sgis/io/opener.py +13 -6
- sgis/io/read_parquet.py +2 -2
- sgis/maps/examine.py +55 -28
- sgis/maps/explore.py +471 -112
- sgis/maps/httpserver.py +12 -12
- sgis/maps/legend.py +285 -134
- sgis/maps/map.py +248 -129
- sgis/maps/maps.py +123 -119
- sgis/maps/thematicmap.py +260 -94
- sgis/maps/tilesources.py +3 -8
- sgis/networkanalysis/_get_route.py +5 -4
- sgis/networkanalysis/_od_cost_matrix.py +44 -1
- sgis/networkanalysis/_points.py +10 -4
- sgis/networkanalysis/_service_area.py +5 -2
- sgis/networkanalysis/closing_network_holes.py +22 -64
- sgis/networkanalysis/cutting_lines.py +58 -46
- sgis/networkanalysis/directednetwork.py +16 -8
- sgis/networkanalysis/finding_isolated_networks.py +6 -5
- sgis/networkanalysis/network.py +15 -13
- sgis/networkanalysis/networkanalysis.py +79 -61
- sgis/networkanalysis/networkanalysisrules.py +21 -17
- sgis/networkanalysis/nodes.py +2 -3
- sgis/networkanalysis/traveling_salesman.py +6 -3
- sgis/parallel/parallel.py +372 -142
- sgis/raster/base.py +9 -3
- sgis/raster/cube.py +331 -213
- sgis/raster/cubebase.py +15 -29
- sgis/raster/image_collection.py +2560 -0
- sgis/raster/indices.py +17 -12
- sgis/raster/raster.py +356 -275
- sgis/raster/sentinel_config.py +104 -0
- sgis/raster/zonal.py +38 -14
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/LICENSE +1 -1
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/METADATA +87 -16
- ssb_sgis-1.0.3.dist-info/RECORD +61 -0
- {ssb_sgis-1.0.1.dist-info → ssb_sgis-1.0.3.dist-info}/WHEEL +1 -1
- sgis/raster/bands.py +0 -48
- sgis/raster/gradient.py +0 -78
- sgis/raster/methods_as_functions.py +0 -124
- sgis/raster/torchgeo.py +0 -150
- ssb_sgis-1.0.1.dist-info/RECORD +0 -63
sgis/geopandas_tools/general.py
CHANGED
|
@@ -1,30 +1,39 @@
|
|
|
1
1
|
import numbers
|
|
2
2
|
import warnings
|
|
3
|
-
from collections.abc import Hashable
|
|
3
|
+
from collections.abc import Hashable
|
|
4
|
+
from collections.abc import Iterable
|
|
4
5
|
from typing import Any
|
|
5
6
|
|
|
6
7
|
import joblib
|
|
7
8
|
import numpy as np
|
|
8
9
|
import pandas as pd
|
|
9
10
|
import pyproj
|
|
10
|
-
from geopandas import GeoDataFrame
|
|
11
|
-
from geopandas
|
|
11
|
+
from geopandas import GeoDataFrame
|
|
12
|
+
from geopandas import GeoSeries
|
|
13
|
+
from geopandas.array import GeometryArray
|
|
14
|
+
from geopandas.array import GeometryDtype
|
|
12
15
|
from numpy.typing import NDArray
|
|
13
|
-
from shapely import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
make_valid,
|
|
22
|
-
)
|
|
16
|
+
from shapely import Geometry
|
|
17
|
+
from shapely import get_coordinates
|
|
18
|
+
from shapely import get_exterior_ring
|
|
19
|
+
from shapely import get_interior_ring
|
|
20
|
+
from shapely import get_num_interior_rings
|
|
21
|
+
from shapely import get_parts
|
|
22
|
+
from shapely import linestrings
|
|
23
|
+
from shapely import make_valid
|
|
23
24
|
from shapely import points as shapely_points
|
|
24
25
|
from shapely import unary_union
|
|
25
|
-
from shapely.geometry import LineString
|
|
26
|
+
from shapely.geometry import LineString
|
|
27
|
+
from shapely.geometry import Point
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
try:
|
|
30
|
+
import dask_geopandas
|
|
31
|
+
except ImportError:
|
|
32
|
+
pass
|
|
33
|
+
|
|
34
|
+
from .geometry_types import get_geom_type
|
|
35
|
+
from .geometry_types import make_all_singlepart
|
|
36
|
+
from .geometry_types import to_single_geom_type
|
|
28
37
|
|
|
29
38
|
|
|
30
39
|
def split_geom_types(gdf: GeoDataFrame | GeoSeries) -> tuple[GeoDataFrame | GeoSeries]:
|
|
@@ -79,13 +88,13 @@ def get_common_crs(
|
|
|
79
88
|
actually_different.add(x)
|
|
80
89
|
|
|
81
90
|
if len(actually_different) == 1:
|
|
82
|
-
return
|
|
91
|
+
return next(iter(actually_different))
|
|
83
92
|
raise ValueError("'crs' mismatch.", truthy_crs)
|
|
84
93
|
|
|
85
94
|
return pyproj.CRS(truthy_crs[0])
|
|
86
95
|
|
|
87
96
|
|
|
88
|
-
def is_bbox_like(obj) -> bool:
|
|
97
|
+
def is_bbox_like(obj: Any) -> bool:
|
|
89
98
|
if (
|
|
90
99
|
hasattr(obj, "__iter__")
|
|
91
100
|
and len(obj) == 4
|
|
@@ -114,6 +123,7 @@ def _push_geom_col(gdf: GeoDataFrame) -> GeoDataFrame:
|
|
|
114
123
|
|
|
115
124
|
|
|
116
125
|
def drop_inactive_geometry_columns(gdf: GeoDataFrame) -> GeoDataFrame:
|
|
126
|
+
"""Removes geometry columns in a GeoDataFrame if they are not active."""
|
|
117
127
|
for col in gdf.columns:
|
|
118
128
|
if (
|
|
119
129
|
isinstance(gdf[col].dtype, GeometryDtype)
|
|
@@ -123,7 +133,7 @@ def drop_inactive_geometry_columns(gdf: GeoDataFrame) -> GeoDataFrame:
|
|
|
123
133
|
return gdf
|
|
124
134
|
|
|
125
135
|
|
|
126
|
-
def
|
|
136
|
+
def _rename_geometry_if(gdf: GeoDataFrame) -> GeoDataFrame:
|
|
127
137
|
geom_col = gdf._geometry_column_name
|
|
128
138
|
if geom_col == "geometry" and geom_col in gdf.columns:
|
|
129
139
|
return gdf
|
|
@@ -157,8 +167,8 @@ def clean_geoms(
|
|
|
157
167
|
GeoDataFrame or GeoSeries with fixed geometries and only the rows with valid,
|
|
158
168
|
non-empty and not-NaN/-None geometries.
|
|
159
169
|
|
|
160
|
-
Examples
|
|
161
|
-
|
|
170
|
+
Examples:
|
|
171
|
+
---------
|
|
162
172
|
>>> import sgis as sg
|
|
163
173
|
>>> import pandas as pd
|
|
164
174
|
>>> from shapely import wkt
|
|
@@ -231,8 +241,20 @@ def clean_geoms(
|
|
|
231
241
|
|
|
232
242
|
|
|
233
243
|
def get_grouped_centroids(
|
|
234
|
-
gdf: GeoDataFrame, groupby: str, as_string: bool = True
|
|
244
|
+
gdf: GeoDataFrame, groupby: str | list[str], as_string: bool = True
|
|
235
245
|
) -> pd.Series:
|
|
246
|
+
"""Get the centerpoint of the geometries within a group.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
gdf: GeoDataFrame.
|
|
250
|
+
groupby: column to group by.
|
|
251
|
+
as_string: If True (default), coordinates are returned in
|
|
252
|
+
the format "{x}_{y}". If False, coordinates are returned
|
|
253
|
+
as Points.
|
|
254
|
+
|
|
255
|
+
Returns:
|
|
256
|
+
A pandas.Series of grouped centroids with the index of 'gdf'.
|
|
257
|
+
"""
|
|
236
258
|
centerpoints = gdf.assign(geometry=lambda x: x.centroid)
|
|
237
259
|
|
|
238
260
|
grouped_centerpoints = centerpoints.dissolve(by=groupby).assign(
|
|
@@ -242,9 +264,13 @@ def get_grouped_centroids(
|
|
|
242
264
|
ys = grouped_centerpoints.geometry.y
|
|
243
265
|
|
|
244
266
|
if as_string:
|
|
245
|
-
grouped_centerpoints["wkt"] = [
|
|
267
|
+
grouped_centerpoints["wkt"] = [
|
|
268
|
+
f"{int(x)}_{int(y)}" for x, y in zip(xs, ys, strict=False)
|
|
269
|
+
]
|
|
246
270
|
else:
|
|
247
|
-
grouped_centerpoints["wkt"] = [
|
|
271
|
+
grouped_centerpoints["wkt"] = [
|
|
272
|
+
Point(x, y) for x, y in zip(xs, ys, strict=False)
|
|
273
|
+
]
|
|
248
274
|
|
|
249
275
|
return gdf[groupby].map(grouped_centerpoints["wkt"])
|
|
250
276
|
|
|
@@ -258,12 +284,20 @@ def sort_large_first(gdf: GeoDataFrame | GeoSeries) -> GeoDataFrame | GeoSeries:
|
|
|
258
284
|
Returns:
|
|
259
285
|
A GeoDataFrame or GeoSeries sorted from large to small in area.
|
|
260
286
|
|
|
261
|
-
Examples
|
|
262
|
-
|
|
287
|
+
Examples:
|
|
288
|
+
---------
|
|
263
289
|
Create GeoDataFrame with NaN values.
|
|
264
290
|
|
|
265
291
|
>>> import sgis as sg
|
|
266
|
-
>>> df = sg.
|
|
292
|
+
>>> df = sg.to_gdf(
|
|
293
|
+
... [
|
|
294
|
+
... (0, 1),
|
|
295
|
+
... (1, 0),
|
|
296
|
+
... (1, 1),
|
|
297
|
+
... (0, 0),
|
|
298
|
+
... (0.5, 0.5),
|
|
299
|
+
... ]
|
|
300
|
+
... )
|
|
267
301
|
>>> df.geometry = df.buffer([4, 1, 2, 3, 5])
|
|
268
302
|
>>> df["col"] = [None, 1, 2, None, 1]
|
|
269
303
|
>>> df["col2"] = [None, 1, 2, 3, None]
|
|
@@ -299,16 +333,6 @@ def sort_large_first(gdf: GeoDataFrame | GeoSeries) -> GeoDataFrame | GeoSeries:
|
|
|
299
333
|
return gdf.iloc[list(sorted_areas)]
|
|
300
334
|
|
|
301
335
|
|
|
302
|
-
def sort_df(
|
|
303
|
-
df: pd.DataFrame | GeoDataFrame, sort_col: pd.Series
|
|
304
|
-
) -> pd.DataFrame | GeoDataFrame:
|
|
305
|
-
value_mapper: dict[int, Any] = dict(enumerate(sort_col.values))
|
|
306
|
-
sorted_indices = dict(
|
|
307
|
-
reversed(sorted(value_mapper.items(), key=lambda item: item[1]))
|
|
308
|
-
)
|
|
309
|
-
return df.iloc[list(sorted_indices)]
|
|
310
|
-
|
|
311
|
-
|
|
312
336
|
def sort_long_first(gdf: GeoDataFrame | GeoSeries) -> GeoDataFrame | GeoSeries:
|
|
313
337
|
"""Sort GeoDataFrame by length in decending order.
|
|
314
338
|
|
|
@@ -402,8 +426,8 @@ def random_points(n: int, loc: float | int = 0.5) -> GeoDataFrame:
|
|
|
402
426
|
Returns:
|
|
403
427
|
A GeoDataFrame of points with n rows.
|
|
404
428
|
|
|
405
|
-
Examples
|
|
406
|
-
|
|
429
|
+
Examples:
|
|
430
|
+
---------
|
|
407
431
|
>>> import sgis as sg
|
|
408
432
|
>>> points = sg.random_points(10_000)
|
|
409
433
|
>>> points
|
|
@@ -451,6 +475,16 @@ def random_points(n: int, loc: float | int = 0.5) -> GeoDataFrame:
|
|
|
451
475
|
|
|
452
476
|
|
|
453
477
|
def random_points_in_polygons(gdf: GeoDataFrame, n: int, seed=None) -> GeoDataFrame:
|
|
478
|
+
"""Creates a GeoDataFrame with n random points within the geometries of 'gdf'.
|
|
479
|
+
|
|
480
|
+
Args:
|
|
481
|
+
gdf: A GeoDataFrame.
|
|
482
|
+
n: Number of points/rows to create.
|
|
483
|
+
seed: Optional random seet.
|
|
484
|
+
|
|
485
|
+
Returns:
|
|
486
|
+
A GeoDataFrame of points with n rows.
|
|
487
|
+
"""
|
|
454
488
|
all_points = []
|
|
455
489
|
|
|
456
490
|
rng = np.random.default_rng(seed)
|
|
@@ -492,8 +526,8 @@ def to_lines(*gdfs: GeoDataFrame, copy: bool = True) -> GeoDataFrame:
|
|
|
492
526
|
ignored. This is because the union overlay used if multiple GeoDataFrames
|
|
493
527
|
always ignores the index.
|
|
494
528
|
|
|
495
|
-
Examples
|
|
496
|
-
|
|
529
|
+
Examples:
|
|
530
|
+
---------
|
|
497
531
|
Convert single polygon to linestring.
|
|
498
532
|
|
|
499
533
|
>>> import sgis as sg
|
|
@@ -525,7 +559,6 @@ def to_lines(*gdfs: GeoDataFrame, copy: bool = True) -> GeoDataFrame:
|
|
|
525
559
|
>>> lines["l"] = lines.length
|
|
526
560
|
>>> sg.qtm(lines, "l")
|
|
527
561
|
"""
|
|
528
|
-
|
|
529
562
|
if not all(isinstance(gdf, (GeoSeries, GeoDataFrame)) for gdf in gdfs):
|
|
530
563
|
raise TypeError("gdf must be GeoDataFrame or GeoSeries")
|
|
531
564
|
|
|
@@ -534,7 +567,6 @@ def to_lines(*gdfs: GeoDataFrame, copy: bool = True) -> GeoDataFrame:
|
|
|
534
567
|
|
|
535
568
|
def _shapely_geometry_to_lines(geom):
|
|
536
569
|
"""Get all lines from the exterior and interiors of a Polygon."""
|
|
537
|
-
|
|
538
570
|
# if lines (points are not allowed in this function)
|
|
539
571
|
if geom.area == 0:
|
|
540
572
|
return geom
|
|
@@ -664,11 +696,11 @@ def _determine_geom_type_args(
|
|
|
664
696
|
return gdf, geom_type, keep_geom_type
|
|
665
697
|
|
|
666
698
|
|
|
667
|
-
def
|
|
699
|
+
def _merge_geometries(geoms: GeoSeries, grid_size=None) -> Geometry:
|
|
668
700
|
return make_valid(unary_union(geoms, grid_size=grid_size))
|
|
669
701
|
|
|
670
702
|
|
|
671
|
-
def
|
|
703
|
+
def _parallel_unary_union(
|
|
672
704
|
gdf: GeoDataFrame, n_jobs: int = 1, by=None, grid_size=None, **kwargs
|
|
673
705
|
) -> list[Geometry]:
|
|
674
706
|
try:
|
|
@@ -702,7 +734,7 @@ def parallel_unary_union(
|
|
|
702
734
|
return dissolved.geometry
|
|
703
735
|
|
|
704
736
|
|
|
705
|
-
def
|
|
737
|
+
def _parallel_unary_union_geoseries(
|
|
706
738
|
ser: GeoSeries, n_jobs: int = 1, grid_size=None, **kwargs
|
|
707
739
|
) -> list[Geometry]:
|
|
708
740
|
if ser.crs is None:
|
|
@@ -725,7 +757,7 @@ def parallel_unary_union_geoseries(
|
|
|
725
757
|
return dissolved.geometry
|
|
726
758
|
|
|
727
759
|
|
|
728
|
-
def
|
|
760
|
+
def _parallel_unary_union(
|
|
729
761
|
gdf: GeoDataFrame, n_jobs: int = 1, by=None, grid_size=None, **kwargs
|
|
730
762
|
) -> list[Geometry]:
|
|
731
763
|
try:
|
|
@@ -737,13 +769,13 @@ def parallel_unary_union(
|
|
|
737
769
|
delayed_operations = []
|
|
738
770
|
for _, geoms in gdf.groupby(by, **kwargs)[geom_col]:
|
|
739
771
|
delayed_operations.append(
|
|
740
|
-
joblib.delayed(
|
|
772
|
+
joblib.delayed(_merge_geometries)(geoms, grid_size=grid_size)
|
|
741
773
|
)
|
|
742
774
|
|
|
743
775
|
return parallel(delayed_operations)
|
|
744
776
|
|
|
745
777
|
|
|
746
|
-
def
|
|
778
|
+
def _parallel_unary_union_geoseries(
|
|
747
779
|
ser: GeoSeries, n_jobs: int = 1, grid_size=None, **kwargs
|
|
748
780
|
) -> list[Geometry]:
|
|
749
781
|
|
|
@@ -756,18 +788,18 @@ def parallel_unary_union_geoseries(
|
|
|
756
788
|
delayed_operations = []
|
|
757
789
|
for _, geoms in many_hits.groupby(**kwargs):
|
|
758
790
|
delayed_operations.append(
|
|
759
|
-
joblib.delayed(
|
|
791
|
+
joblib.delayed(_merge_geometries)(geoms, grid_size=grid_size)
|
|
760
792
|
)
|
|
761
793
|
|
|
762
794
|
dissolved = pd.Series(
|
|
763
795
|
parallel(delayed_operations),
|
|
764
|
-
index=is_one_hit[lambda x: x
|
|
796
|
+
index=is_one_hit[lambda x: x is False].index.unique(),
|
|
765
797
|
)
|
|
766
798
|
|
|
767
799
|
return pd.concat([dissolved, one_hit]).sort_index().values
|
|
768
800
|
|
|
769
801
|
|
|
770
|
-
def
|
|
802
|
+
def _parallel_unary_union_geoseries(
|
|
771
803
|
ser: GeoSeries, n_jobs: int = 1, grid_size=None, **kwargs
|
|
772
804
|
) -> list[Geometry]:
|
|
773
805
|
|
|
@@ -775,7 +807,7 @@ def parallel_unary_union_geoseries(
|
|
|
775
807
|
delayed_operations = []
|
|
776
808
|
for _, geoms in ser.groupby(**kwargs):
|
|
777
809
|
delayed_operations.append(
|
|
778
|
-
joblib.delayed(
|
|
810
|
+
joblib.delayed(_merge_geometries)(geoms, grid_size=grid_size)
|
|
779
811
|
)
|
|
780
812
|
|
|
781
813
|
return parallel(delayed_operations)
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
"""Check and set geometry type."""
|
|
2
|
+
|
|
2
3
|
import numpy as np
|
|
3
4
|
import pandas as pd
|
|
4
5
|
import shapely
|
|
5
|
-
from geopandas import GeoDataFrame
|
|
6
|
+
from geopandas import GeoDataFrame
|
|
7
|
+
from geopandas import GeoSeries
|
|
6
8
|
from geopandas.array import GeometryArray
|
|
7
9
|
from shapely import Geometry
|
|
8
10
|
|
|
@@ -10,6 +12,18 @@ from shapely import Geometry
|
|
|
10
12
|
def make_all_singlepart(
|
|
11
13
|
gdf: GeoDataFrame | GeoSeries, index_parts: bool = False, ignore_index: bool = False
|
|
12
14
|
) -> GeoDataFrame | GeoSeries:
|
|
15
|
+
"""Make all geometries single part.
|
|
16
|
+
|
|
17
|
+
This means doing either 0, 1 or 2 calls to the explode method.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
gdf: GeoDataFrame
|
|
21
|
+
index_parts: Defaults to False.
|
|
22
|
+
ignore_index: Defaults to False.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
A GeoDataFrame of singlepart geometries.
|
|
26
|
+
"""
|
|
13
27
|
# only explode if nessecary
|
|
14
28
|
if (
|
|
15
29
|
index_parts or ignore_index
|
|
@@ -25,7 +39,7 @@ def make_all_singlepart(
|
|
|
25
39
|
|
|
26
40
|
|
|
27
41
|
def to_single_geom_type(
|
|
28
|
-
gdf: GeoDataFrame | GeoSeries,
|
|
42
|
+
gdf: GeoDataFrame | GeoSeries | Geometry | GeometryArray | np.ndarray,
|
|
29
43
|
geom_type: str,
|
|
30
44
|
ignore_index: bool = False,
|
|
31
45
|
) -> GeoDataFrame | GeoSeries:
|
|
@@ -49,8 +63,8 @@ def to_single_geom_type(
|
|
|
49
63
|
TypeError: If incorrect gdf type.
|
|
50
64
|
ValueError: If 'geom_type' is neither 'polygon', 'line' or 'point'.
|
|
51
65
|
|
|
52
|
-
Examples
|
|
53
|
-
|
|
66
|
+
Examples:
|
|
67
|
+
---------
|
|
54
68
|
First create a GeoDataFrame of mixed geometries.
|
|
55
69
|
|
|
56
70
|
>>> from sgis import to_gdf, to_single_geom_type
|
|
@@ -96,7 +110,7 @@ def to_single_geom_type(
|
|
|
96
110
|
arr = np.vectorize(_shapely_to_single_geom_type)(gdf, geom_type)
|
|
97
111
|
return arr[~shapely.is_empty(arr)]
|
|
98
112
|
|
|
99
|
-
if not isinstance(gdf, (GeoDataFrame, GeoSeries)):
|
|
113
|
+
if not isinstance(gdf, (GeoDataFrame, GeoSeries)): # type: ignore [unreachable]
|
|
100
114
|
raise TypeError(f"'gdf' should be GeoDataFrame or GeoSeries, got {type(gdf)}")
|
|
101
115
|
|
|
102
116
|
# explode collections to single-typed geometries
|
|
@@ -122,7 +136,7 @@ def to_single_geom_type(
|
|
|
122
136
|
return gdf.reset_index(drop=True) if ignore_index else gdf
|
|
123
137
|
|
|
124
138
|
|
|
125
|
-
def _shapely_to_single_geom_type(geom, geom_type):
|
|
139
|
+
def _shapely_to_single_geom_type(geom: Geometry, geom_type: str) -> Geometry:
|
|
126
140
|
parts = shapely.get_parts(geom)
|
|
127
141
|
return shapely.unary_union(
|
|
128
142
|
[part for part in parts if geom_type.lower() in part.geom_type.lower()]
|
|
@@ -141,8 +155,8 @@ def get_geom_type(gdf: GeoDataFrame | GeoSeries) -> str:
|
|
|
141
155
|
Raises:
|
|
142
156
|
TypeError: If 'gdf' is not of type GeoDataFrame or GeoSeries.
|
|
143
157
|
|
|
144
|
-
Examples
|
|
145
|
-
|
|
158
|
+
Examples:
|
|
159
|
+
---------
|
|
146
160
|
>>> from sgis import to_gdf, get_geom_type
|
|
147
161
|
>>> gdf = to_gdf([0, 0])
|
|
148
162
|
>>> gdf
|
|
@@ -189,8 +203,8 @@ def is_single_geom_type(gdf: GeoDataFrame | GeoSeries) -> bool:
|
|
|
189
203
|
Raises:
|
|
190
204
|
TypeError: If 'gdf' is not of type GeoDataFrame or GeoSeries.
|
|
191
205
|
|
|
192
|
-
Examples
|
|
193
|
-
|
|
206
|
+
Examples:
|
|
207
|
+
---------
|
|
194
208
|
>>> from sgis import to_gdf, get_geom_type
|
|
195
209
|
>>> gdf = to_gdf([0, 0])
|
|
196
210
|
>>> gdf
|
|
@@ -10,9 +10,10 @@ types.
|
|
|
10
10
|
|
|
11
11
|
import numpy as np
|
|
12
12
|
import shapely
|
|
13
|
-
from geopandas import GeoDataFrame
|
|
14
|
-
from
|
|
15
|
-
from
|
|
13
|
+
from geopandas import GeoDataFrame
|
|
14
|
+
from geopandas import GeoSeries
|
|
15
|
+
from pandas import DataFrame
|
|
16
|
+
from pandas import Series
|
|
16
17
|
from sklearn.neighbors import NearestNeighbors
|
|
17
18
|
|
|
18
19
|
from .conversion import coordinate_array
|
|
@@ -48,8 +49,8 @@ def get_neighbor_indices(
|
|
|
48
49
|
ValueError: If gdf and neighbors do not have the same coordinate reference
|
|
49
50
|
system.
|
|
50
51
|
|
|
51
|
-
Examples
|
|
52
|
-
|
|
52
|
+
Examples:
|
|
53
|
+
---------
|
|
53
54
|
>>> from sgis import get_neighbor_indices, to_gdf
|
|
54
55
|
>>> points = to_gdf([(0, 0), (0.5, 0.5)])
|
|
55
56
|
>>> points
|
|
@@ -96,7 +97,6 @@ def get_neighbor_indices(
|
|
|
96
97
|
['a' 'a' 'b' 'b']
|
|
97
98
|
|
|
98
99
|
"""
|
|
99
|
-
|
|
100
100
|
if gdf.crs != neighbors.crs:
|
|
101
101
|
raise ValueError(f"'crs' mismatch. Got {gdf.crs} and {neighbors.crs}")
|
|
102
102
|
|
|
@@ -152,8 +152,8 @@ def get_all_distances(
|
|
|
152
152
|
ValueError: If the coordinate reference system of 'gdf' and 'neighbors' are
|
|
153
153
|
not the same.
|
|
154
154
|
|
|
155
|
-
Examples
|
|
156
|
-
|
|
155
|
+
Examples:
|
|
156
|
+
---------
|
|
157
157
|
>>> from sgis import get_all_distances, random_points
|
|
158
158
|
>>> points = random_points(100)
|
|
159
159
|
>>> neighbors = random_points(100)
|
|
@@ -248,7 +248,6 @@ def sjoin_within_distance(
|
|
|
248
248
|
**kwargs,
|
|
249
249
|
) -> GeoDataFrame:
|
|
250
250
|
"""Sjoin with a buffer on the right GeoDataFrame and adds a distance column."""
|
|
251
|
-
|
|
252
251
|
new_neighbor_cols = {"__left_range_idx": range(len(neighbors))}
|
|
253
252
|
if distance:
|
|
254
253
|
new_neighbor_cols[neighbors._geometry_column_name] = lambda x: x.buffer(
|
|
@@ -297,8 +296,8 @@ def get_k_nearest_neighbors(
|
|
|
297
296
|
ValueError: If the coordinate reference system of 'gdf' and 'neighbors' are
|
|
298
297
|
not the same.
|
|
299
298
|
|
|
300
|
-
Examples
|
|
301
|
-
|
|
299
|
+
Examples:
|
|
300
|
+
---------
|
|
302
301
|
Make some random points.
|
|
303
302
|
|
|
304
303
|
>>> from sgis import get_k_nearest_neighbors, random_points
|
|
@@ -430,6 +429,19 @@ def k_nearest_neighbors(
|
|
|
430
429
|
k: int | None = None,
|
|
431
430
|
strict: bool = False,
|
|
432
431
|
) -> tuple[np.ndarray[float], np.ndarray[int]]:
|
|
432
|
+
"""Finds nearest neighbors for an array of coordinates to another array of coordinates.
|
|
433
|
+
|
|
434
|
+
Args:
|
|
435
|
+
from_array: Numpy array of coordinates.
|
|
436
|
+
to_array: Numpy array of coordinates.
|
|
437
|
+
k: Number of neighbors to find.
|
|
438
|
+
strict: If True (not default), an exception is raised
|
|
439
|
+
if k is larger than the length of 'to_array'.
|
|
440
|
+
|
|
441
|
+
Returns a tuple of arrays, one with distances and one with indices
|
|
442
|
+
of the neighbors.
|
|
443
|
+
|
|
444
|
+
"""
|
|
433
445
|
if not len(to_array) or not len(from_array):
|
|
434
446
|
return np.array([]), np.array([])
|
|
435
447
|
|