GeoPandas extends pandas functionality to handle geographic and geospatial data operations with GeoSeries and GeoDataFrame classes.
—
GeoPandas provides comprehensive testing utilities for validating geospatial data structures and operations. These utilities enable robust testing of spatial data processing workflows and ensure correctness of geometric operations.
Functions for testing equality between geospatial objects with appropriate tolerance handling.
def assert_geoseries_equal(left, right, check_dtype=True, check_index_type=True, check_series_type=True, check_names=True, check_crs=True, check_geom_type=False, check_less_precise=False, normalize=False):
"""
Assert that two GeoSeries are equal.
Parameters:
- left: GeoSeries to compare
- right: GeoSeries to compare
- check_dtype: Whether to check dtype equivalence
- check_index_type: Whether to check index type equivalence
- check_series_type: Whether to check series type equivalence
- check_names: Whether to check names equivalence
- check_crs: Whether to check CRS equivalence
- check_geom_type: Whether to check geometry type consistency
- check_less_precise: Whether to use less precise comparison for coordinates
- normalize: Whether to normalize geometries before comparison
Raises:
- AssertionError: If GeoSeries are not equal according to criteria
"""
...
def assert_geodataframe_equal(left, right, check_dtype=True, check_index_type=True, check_frame_type=True, check_names=True, check_crs=True, check_geom_type=False, check_less_precise=False, normalize=False):
"""
Assert that two GeoDataFrames are equal.
Parameters:
- left: GeoDataFrame to compare
- right: GeoDataFrame to compare
- check_dtype: Whether to check dtype equivalence
- check_index_type: Whether to check index type equivalence
- check_frame_type: Whether to check frame type equivalence
- check_names: Whether to check names equivalence
- check_crs: Whether to check CRS equivalence
- check_geom_type: Whether to check geometry type consistency
- check_less_precise: Whether to use less precise comparison for coordinates
- normalize: Whether to normalize geometries before comparison
Raises:
- AssertionError: If GeoDataFrames are not equal according to criteria
"""
...
def assert_index_equal(left, right, exact='equiv', check_names=True, check_exact=True, check_categorical=True, check_order=True, rtol=1e-5, atol=1e-8, obj='Index'):
"""
Assert that two spatial indices are equal.
Parameters:
- left: Index to compare
- right: Index to compare
- exact: Whether to check index type exactly
- check_names: Whether to check names equivalence
- check_exact: Whether to compare exactly
- check_categorical: Whether to check categorical exactly
- check_order: Whether to check order
- rtol: Relative tolerance for numeric comparison
- atol: Absolute tolerance for numeric comparison
- obj: Object name for error messages
Raises:
- AssertionError: If indices are not equal according to criteria
"""
...Function for displaying version information about GeoPandas and its dependencies.
def show_versions():
"""
Print version information for GeoPandas and its dependencies.
This function displays version information for:
- GeoPandas itself
- Python interpreter
- Core dependencies (pandas, shapely, pyproj, etc.)
- Optional dependencies (matplotlib, etc.)
- System information
Useful for debugging and reporting issues.
"""
...import geopandas as gpd
from geopandas.testing import assert_geoseries_equal
from shapely.geometry import Point, Polygon
# Create test GeoSeries
gs1 = gpd.GeoSeries([Point(0, 0), Point(1, 1)], crs='EPSG:4326')
gs2 = gpd.GeoSeries([Point(0, 0), Point(1, 1)], crs='EPSG:4326')
# Test equality - should pass
assert_geoseries_equal(gs1, gs2)
# Test with different CRS - should fail unless check_crs=False
gs3 = gpd.GeoSeries([Point(0, 0), Point(1, 1)], crs='EPSG:3857')
try:
assert_geoseries_equal(gs1, gs3)
except AssertionError:
print("CRS mismatch detected")
# Ignore CRS differences
assert_geoseries_equal(gs1, gs3, check_crs=False)from geopandas.testing import assert_geodataframe_equal
# Create test GeoDataFrames
gdf1 = gpd.GeoDataFrame({
'name': ['A', 'B'],
'geometry': [Point(0, 0), Point(1, 1)]
}, crs='EPSG:4326')
gdf2 = gpd.GeoDataFrame({
'name': ['A', 'B'],
'geometry': [Point(0, 0), Point(1, 1)]
}, crs='EPSG:4326')
# Test equality
assert_geodataframe_equal(gdf1, gdf2)
# Test with different column order
gdf3 = gpd.GeoDataFrame({
'geometry': [Point(0, 0), Point(1, 1)],
'name': ['A', 'B']
}, crs='EPSG:4326')
# Should still be equal (column order doesn't matter by default)
assert_geodataframe_equal(gdf1, gdf3)# Test that geometric operations preserve expected properties
original = gpd.GeoSeries([
Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
], crs='EPSG:4326')
# Buffer and then negative buffer should approximate original
buffered = original.buffer(0.1)
unbuffered = buffered.buffer(-0.1)
# Use less precise comparison due to floating point operations
assert_geoseries_equal(original, unbuffered, check_less_precise=True)# Test CRS transformations
gdf_wgs84 = gpd.GeoDataFrame({
'geometry': [Point(-74.0, 40.7)] # New York
}, crs='EPSG:4326')
# Transform to Web Mercator and back
gdf_mercator = gdf_wgs84.to_crs('EPSG:3857')
gdf_back = gdf_mercator.to_crs('EPSG:4326')
# Should be approximately equal (may have small precision differences)
assert_geodataframe_equal(gdf_wgs84, gdf_back, check_less_precise=True)from shapely.geometry import Polygon
# Create geometries that are topologically equal but with different coordinate order
poly1 = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)])
poly2 = Polygon([(1, 0), (1, 1), (0, 1), (0, 0)]) # Different starting point
gs1 = gpd.GeoSeries([poly1])
gs2 = gpd.GeoSeries([poly2])
# Direct comparison might fail due to coordinate ordering
try:
assert_geoseries_equal(gs1, gs2)
except AssertionError:
print("Coordinate order mismatch")
# Use normalize=True to handle coordinate ordering differences
assert_geoseries_equal(gs1, gs2, normalize=True)# Test that spatial operations produce expected results
circle = gpd.GeoSeries([Point(0, 0).buffer(1)])
square = gpd.GeoSeries([Polygon([(-1, -1), (1, -1), (1, 1), (-1, 1)])])
# Test intersection
intersection = gpd.overlay(
gpd.GeoDataFrame(geometry=circle),
gpd.GeoDataFrame(geometry=square),
how='intersection'
)
# Intersection should not be empty
assert not intersection.geometry.is_empty.any()
# Area should be less than both original geometries
assert (intersection.geometry.area < circle.area).all()
assert (intersection.geometry.area < square.area).all()from geopandas.tools import show_versions
# Display comprehensive version information
show_versions()
# Example output:
# INSTALLED VERSIONS
# ------------------
# commit : None
# python : 3.9.7
# python-bits : 64
# OS : Linux
# OS-release : 5.4.0
# machine : x86_64
# processor : x86_64
# byteorder : little
# LC_ALL : None
# LANG : en_US.UTF-8
# LOCALE : en_US.UTF-8
#
# geopandas : 0.12.0
# pandas : 1.4.2
# fiona : 1.8.21
# numpy : 1.21.6
# shapely : 1.8.2
# pyproj : 3.3.1
# ...def test_spatial_workflow():
"""Example of testing a complete spatial analysis workflow."""
# 1. Create test data
points = gpd.GeoDataFrame({
'id': [1, 2, 3],
'geometry': [Point(0, 0), Point(1, 1), Point(2, 2)]
}, crs='EPSG:4326')
polygons = gpd.GeoDataFrame({
'zone': ['A', 'B'],
'geometry': [
Polygon([(-0.5, -0.5), (0.5, -0.5), (0.5, 0.5), (-0.5, 0.5)]),
Polygon([(0.5, 0.5), (1.5, 0.5), (1.5, 1.5), (0.5, 1.5)])
]
}, crs='EPSG:4326')
# 2. Perform spatial join
result = gpd.sjoin(points, polygons, how='left', predicate='within')
# 3. Test results
expected_zones = ['A', 'B', None] # Point 3 should be outside both zones
# Check that join produced expected zone assignments
for i, expected_zone in enumerate(expected_zones):
if expected_zone is None:
assert pd.isna(result.loc[i, 'zone'])
else:
assert result.loc[i, 'zone'] == expected_zone
# 4. Test geometric consistency
assert_geodataframe_equal(
result[['id', 'geometry']],
points[['id', 'geometry']]
)
print("Spatial workflow test passed!")
# Run the test
test_spatial_workflow()Install with Tessl CLI
npx tessl i tessl/pypi-geopandas