初次提交

This commit is contained in:
2026-03-04 17:07:07 +08:00
commit af988ea7b9
37 changed files with 3674 additions and 0 deletions

80
tests/test_analysis.py Normal file
View File

@@ -0,0 +1,80 @@
"""tests/test_analysis.py —— 空间分析单元测试。"""
import pytest
import geopandas as gpd
from shapely.geometry import Point, Polygon
from geo_tools.analysis.spatial_ops import overlay, select_by_location
from geo_tools.analysis.stats import area_weighted_mean, count_by_polygon, summarize_attributes
class TestOverlay:
def test_intersection(self, sample_multi_polygon_gdf):
poly_a = sample_multi_polygon_gdf.iloc[[0]].copy()
poly_b = sample_multi_polygon_gdf.iloc[[1]].copy()
result = overlay(poly_a, poly_b, how="intersection")
assert len(result) >= 1
assert result.geometry.is_valid.all()
def test_union(self, sample_multi_polygon_gdf):
poly_a = sample_multi_polygon_gdf.iloc[[0]].copy()
poly_b = sample_multi_polygon_gdf.iloc[[1]].copy()
result = overlay(poly_a, poly_b, how="union", keep_geom_type=False)
assert result.geometry.is_valid.all()
class TestSelectByLocation:
def test_select_points_in_polygon(self, sample_points_gdf, sample_polygon_gdf):
# polygon 覆盖华北区,应选中 北京 点
result = select_by_location(sample_points_gdf, sample_polygon_gdf, predicate="intersects")
assert len(result) >= 1
def test_select_within(self, sample_points_gdf, sample_polygon_gdf):
result = select_by_location(sample_points_gdf, sample_polygon_gdf, predicate="within")
assert len(result) >= 0 # 可能有点在边界上
class TestAreaWeightedMean:
def test_global_weighted_mean(self, sample_multi_polygon_gdf):
result = area_weighted_mean(sample_multi_polygon_gdf, value_col="value")
assert "area_weighted_mean" in result.index
assert result["area_weighted_mean"] > 0
def test_grouped_weighted_mean(self, sample_multi_polygon_gdf):
gdf = sample_multi_polygon_gdf.copy()
gdf["group"] = ["A", "B"]
result = area_weighted_mean(gdf, value_col="value", group_col="group")
assert "area_weighted_mean" in result.columns
assert len(result) == 2
class TestSummarizeAttributes:
def test_basic_summary(self, sample_points_gdf):
result = summarize_attributes(sample_points_gdf, columns=["value"])
assert "column" in result.columns
assert "mean" in result.columns
def test_grouped_summary(self, sample_points_gdf):
gdf = sample_points_gdf.copy()
gdf["group"] = ["北方", "东部", "南方"]
result = summarize_attributes(gdf, columns=["value"], group_col="group")
# 每组一行
assert len(result) == 3
class TestCountByPolygon:
def test_count_points_in_polygons(self, sample_points_gdf, sample_polygon_gdf):
result = count_by_polygon(sample_points_gdf, sample_polygon_gdf)
assert "point_count" in result.columns
assert result["point_count"].dtype.kind == "i" # 整数
def test_polygon_with_no_points(self):
# 南海中的 polygon不含任何点
poly = Polygon([(115, 10), (120, 10), (120, 15), (115, 15)])
polygons = gpd.GeoDataFrame({"id": [1]}, geometry=[poly], crs="EPSG:4326")
points = gpd.GeoDataFrame(
geometry=[Point(116.4, 39.9)], # 北京,不在 polygon 内
crs="EPSG:4326",
)
result = count_by_polygon(points, polygons)
assert result["point_count"].iloc[0] == 0