初次提交
This commit is contained in:
80
tests/test_analysis.py
Normal file
80
tests/test_analysis.py
Normal 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
|
||||
Reference in New Issue
Block a user