Files
geo_tools/tests/test_analysis.py
2026-03-04 17:07:07 +08:00

81 lines
3.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""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