SuperAPI AI Directory

geopandas

Data & analytics

View repository

Updated 10-16 09:45

About this skill

GeoPandas

Overview

GeoPandas is the core library for geospatial vector data processing in Python, extending pandas DataFrame with support for geometry columns. The core classes GeoDataFrame(inherits pandas.DataFrame) and GeoSeries(inherits pandas.Series) provide geometric operations through Shapely, coordinate system management through pyproj, and file IO through pyogrio/fiona.

Dependencies

Core Dependencies Minimum Version Purpose
pandas >= 2.2.0 DataFrame base class
shapely >= 2.1.0 Geometry objects and operations (GEOS)
pyproj >= 3.7.0 CRS handling and coordinate transformation
pyogrio >= 0.8 Default file IO engine (GDAL/OGR)
numpy >= 2 Array operations
Optional Dependencies Purpose
matplotlib >= 3.9 Static map plotting .plot()
folium Interactive maps .explore()
mapclassify >= 2.7 Choropleth classification schemes
fiona >= 1.8.21 Alternative file IO engine
pyarrow >= 15.0.0 Parquet/Feather/Arrow support
geopy Geocoding
SQLAlchemy >= 2.0 + GeoAlchemy2 PostGIS read/write
xyzservices Tile basemap services

Global Configuration

import geopandas as gpd
gpd.options.display_precision  # int|None, WKT 小数位数 (0-16)
gpd.options.io_engine          # None|"pyogrio"|"fiona"

Core Class API

GeoDataFrame

gpd.GeoDataFrame(data=None, *args, geometry=None, crs=None, **kwargs)

Alternative Constructors

Methods Signature
GeoDataFrame.from_dict() (data, geometry=None, crs=None, **kwargs)
GeoDataFrame.from_file() (filename, **kwargs)
GeoDataFrame.from_features() (features, crs=None, columns=None)
GeoDataFrame.from_postgis() (sql, con, geom_col="geom", crs=None, ...)
GeoDataFrame.from_arrow() (table, geometry=None, to_pandas_kwargs=None)

Core Attributes

Attribute Description
.geometry Active geometry column (GeoSeries)
.crs Coordinate reference system (pyproj.CRS)
.active_geometry_name Active geometry column name
.total_bounds Overall bounds [minx, miny, maxx, maxy]
.sindex Spatial index (STRtree)

Geometry Management

Methods Signature
set_geometry() (col, drop=None, inplace=False, crs=None)
rename_geometry() (col, inplace=False)
set_crs() (crs=None, epsg=None, inplace=False, allow_override=False)
to_crs() (crs=None, epsg=None, inplace=False)
estimate_utm_crs() (datum_name="WGS 84") → pyproj.CRS

Spatial operations (GeoDataFrame level)

Methods Signature
dissolve() (by=None, aggfunc="first", as_index=True, sort=True, method="unary", grid_size=None)
explode() (column=None, ignore_index=False, index_parts=False)
sjoin() (df, how="inner", predicate="intersects", lsuffix="left", rsuffix="right")
sjoin_nearest() (right, how="inner", max_distance=None, distance_col=None, exclusive=False)
clip() (mask, keep_geom_type=False, sort=False)
overlay() (right, how="intersection", keep_geom_type=None, make_valid=True)

Serialization Output

Methods Description
to_file(filename, driver=None, ...) Shapefile/GPKG/GeoJSON etc.
to_parquet(path, compression="snappy", geometry_encoding="WKB", ...) GeoParquet
to_feather(path, ...) Feather
to_json(na="null", show_bbox=False, to_wgs84=False, ...) GeoJSON string
to_geo_dict(...) Python dict (FeatureCollection)
to_wkb(hex=False) DataFrame (WKB)
to_wkt() DataFrame (WKT)
to_postgis(name, con, schema=None, if_exists="fail", ...) PostGIS
to_arrow(geometry_encoding="WKB", ...) Arrow Table

GeoSeries

gpd.GeoSeries(data=None, index=None, crs=None, **kwargs)

Alternative Constructors

Methods Signature
GeoSeries.from_wkb() (data, index=None, crs=None, on_invalid="raise")
GeoSeries.from_wkt() (data, index=None, crs=None, on_invalid="raise")
GeoSeries.from_xy() (x, y, z=None, index=None, crs=None)
GeoSeries.from_file() (filename, **kwargs)
GeoSeries.from_arrow() (arr, **kwargs)

Coordinate accessors (Point only)

.x, .y, .z, .m → pandas.Series


Shared geometry attributes and methods (GeoDataFrame.geometry / GeoSeries)

Scalar attributes → pandas.Series

Attribute Return type Description
.area float Area (in CRS units)
.length float Length/perimeter
.geom_type str Geometry type name
.is_valid bool Geometry validity
.is_empty bool Empty geometry check
.is_simple bool Does not self-intersect
.has_z bool Contains z coordinate
.bounds DataFrame Per-geometry (minx, miny, maxx, maxy)
.total_bounds array Overall (minx, miny, maxx, maxy)

Geometry attributes → GeoSeries

.boundary, .centroid, .convex_hull, .envelope, .exterior

Unary geometry methods → GeoSeries

Methods Signature
buffer() (distance, quad_segs=None, **kwargs)
simplify() (tolerance, preserve_topology=True)
representative_point() ()
make_valid() (method="linework", keep_collapsed=True)
normalize() ()
reverse() ()
segmentize() (max_segment_length)
force_2d() ()
force_3d() (z=0)
offset_curve() (distance, quad_segs=8, join_style="round", mitre_limit=5.0)
minimum_rotated_rectangle() ()
minimum_bounding_circle() ()
maximum_inscribed_circle() (tolerance)
concave_hull() (ratio, allow_holes)
extract_unique_points() ()
remove_repeated_points() (tolerance=0.0)
line_merge() (directed=False)
set_precision() (grid_size, mode="valid_output")
orient_polygons() (exterior_cw=False)
constrained_delaunay_triangles() ()

Binary predicates → Series[bool]

contains(other, align=None)          covers(other, align=None)
covered_by(other, align=None)        crosses(other, align=None)
disjoint(other, align=None)          intersects(other, align=None)
overlaps(other, align=None)          touches(other, align=None)
within(other, align=None)            contains_properly(other, align=None)
dwithin(other, distance, align=None)
geom_equals(other, align=None)       geom_equals_exact(other, tolerance, align=None)
geom_equals_identical(other, align=None)
relate_pattern(other, pattern)

Binary geometry operations → GeoSeries

difference(other, align=None)          intersection(other, align=None)
symmetric_difference(other, align=None) union(other, align=None)
shortest_line(other, align=None)       snap(other, tolerance, align=None)
shared_paths(other, align=None)

Distance methods → Series[float]

distance(other, align=None)
hausdorff_distance(other, align=None)
frechet_distance(other, align=None)

Linear referencing

interpolate(distance, normalized=False)  → GeoSeries (线上的点)
project(other, normalized=False)         → Series[float] (沿线距离)

Aggregation methods

union_all(method="unary", grid_size=None)  → 单个 Shapely geometry
intersection_all()                         → 单个 Shapely geometry

Affine transformations → GeoSeries

affine_transform(matrix)
translate(xoff=0.0, yoff=0.0, zoff=0.0)
rotate(angle, origin="center", use_radians=False)
scale(xfact=1.0, yfact=1.0, zfact=1.0, origin="center")
skew(xs=0.0, ys=0.0, origin="center", use_radians=False)
transform(transformation, include_z=False)

Other Methods

Methods Returns Description
clip_by_rect(xmin, ymin, xmax, ymax) GeoSeries Rectangle clipping
relate(other, align=None) Series[str] DE-9IM matrix
count_coordinates() Series[int] Number of coordinate pairs
count_geometries() Series[int] Number of parts of a multi-part geometry
get_coordinates() DataFrame Extract all coordinates
hilbert_distance() Series Hilbert curve distance
is_valid_reason() Series[str] Invalid reason

Spatial index (SpatialIndex)

sindex = gdf.sindex
sindex.query(geometry, predicate=None, sort=False, distance=None)
sindex.nearest(geometry, max_distance=None, return_distance=False, return_all=True, exclusive=False)
sindex.valid_query_predicates  # 有效谓词集合
sindex.size                    # 几何体数量
sindex.is_empty                # 是否为空

IO module

File read/write

gpd.read_file(filename, bbox=None, mask=None, columns=None, rows=None, engine=None, **kwargs)
gdf.to_file(filename, driver=None, schema=None, index=None, **kwargs)
gpd.list_layers(filename)  # → DataFrame (layer_name, geometry_type)

Supported file formats (extension → driver):

Extension Driver
.shp ESRI Shapefile
.json, .geojson GeoJSON
.geojsonl, .geojsons GeoJSONSeq
.gpkg GPKG (GeoPackage)
.gml, .xml GML
.gpx GPX
.csv CSV
.fgb FlatGeobuf
.dxf DXF
.tab, .mif, .mid MapInfo File

Engine options:"pyogrio"(default) or "fiona". Supports all GDAL/OGR drivers.

GeoParquet / Feather

gpd.read_parquet(path, columns=None, storage_options=None, bbox=None, **kwargs)
gpd.read_feather(path, columns=None, **kwargs)
gdf.to_parquet(path, compression="snappy", geometry_encoding="WKB",
               write_covering_bbox=False, schema_version=None, **kwargs)
gdf.to_feather(path, compression=None, schema_version=None, **kwargs)

GeoParquet specification version:"1.0.0", "1.1.0" etc. Geometry encoding:"WKB"(default),"geoarrow"。

Arrow (GeoArrow)

gdf.to_arrow(geometry_encoding="WKB", interleaved=True, include_z=None)
GeoDataFrame.from_arrow(table, geometry=None, to_pandas_kwargs=None)
gs.to_arrow(geometry_encoding="WKB", interleaved=True, include_z=None)
GeoSeries.from_arrow(arr, **kwargs)

PostGIS

gpd.read_postgis(sql, con, geom_col="geom", crs=None, index_col=None, ...)
gdf.to_postgis(name, con, schema=None, if_exists="fail", index=False, ...)

Requires:SQLAlchemy + GeoAlchemy2 + psycopg/psycopg2。

WKB/WKT and coordinate construction

gpd.points_from_xy(x, y, z=None, crs=None)  # → GeometryArray
GeoSeries.from_wkb(data, crs=None, on_invalid="raise")
GeoSeries.from_wkt(data, crs=None, on_invalid="raise")
GeoSeries.from_xy(x, y, z=None, crs=None)

Tools module (tools)

Spatial join

gpd.sjoin(left_df, right_df, how="inner", predicate="intersects",
          lsuffix="left", rsuffix="right", distance=None, on_attribute=None)
  • how: "inner", "left", "right"
  • predicate: "intersects", "within", "contains", "contains_properly", "overlaps", "crosses", "touches", "covers", "covered_by", "dwithin"
  • on_attribute: additional non-spatial join filter column names

Nearest neighbor spatial join

gpd.sjoin_nearest(left_df, right_df, how="inner", max_distance=None,
                  distance_col=None, exclusive=False)

Spatial overlay

gpd.overlay(df1, df2, how="intersection", keep_geom_type=None, make_valid=True)
  • how: "intersection", "union", "identity", "symmetric_difference", "difference"

Clip

gpd.clip(gdf, mask, keep_geom_type=False, sort=False)
  • mask: GeoDataFrame, GeoSeries, (Multi)Polygon, or (minx, miny, maxx, maxy) tuple

Geocoding

gpd.tools.geocode(strings, provider=None, **kwargs)          # → GeoDataFrame
gpd.tools.reverse_geocode(points, provider=None, **kwargs)   # → GeoDataFrame

Requires geopy. Default provider: "photon". Returns a GeoDataFrame containing geometry and address columns.

Other tools

gpd.tools.collect(x, multi=False)  # 收集几何体为多部件
gpd.show_versions()                # 打印依赖版本信息

Visualization

Static plotting (matplotlib)

# GeoSeries
gs.plot(cmap=None, color=None, ax=None, figsize=None, aspect="auto")

# GeoDataFrame — 支持分级设色
gdf.plot(column=None, cmap=None, color=None, ax=None, figsize=None,
         legend=False, scheme=None, k=5, vmin=None, vmax=None,
         markersize=None, categories=None, classification_kwds=None,
         missing_kwds=None, legend_kwds=None, **style_kwds)

scheme parameter requires mapclassify, supports "quantiles", "equal_interval", "fisher_jenks" and other classification schemes.

Interactive maps (folium/leaflet)

gdf.explore(column=None, cmap=None, color=None, m=None,
            tiles="OpenStreetMap", tooltip=True, popup=False,
            categorical=False, legend=True, scheme=None, k=5,
            marker_type=None, marker_kwds={}, style_kwds={},
            tooltip_kwds={}, popup_kwds={}, legend_kwds={}, **kwargs)

Common patterns quick reference

Create GeoDataFrame

import geopandas as gpd
from shapely.geometry import Point, Polygon, LineString

# 从文件读取
gdf = gpd.read_file("data.shp")
gdf = gpd.read_file("data.gpkg", layer="my_layer")
gdf = gpd.read_parquet("data.parquet")

# 从字典创建
gdf = gpd.GeoDataFrame(
    {"name": ["A", "B"], "value": [1, 2],
     "geometry": [Point(0, 0), Point(1, 1)]},
    crs="EPSG:4326"
)

# 从 pandas DataFrame + 坐标列
import pandas as pd
df = pd.DataFrame({"lon": [116.4, 121.5], "lat": [39.9, 31.2], "city": ["北京", "上海"]})
gdf = gpd.GeoDataFrame(df, geometry=gpd.points_from_xy(df.lon, df.lat), crs="EPSG:4326")

# 从 WKT/WKB
gs = gpd.GeoSeries.from_wkt(["POINT (0 0)", "POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))"], crs=4326)

# 从 GeoJSON FeatureCollection
gdf = gpd.GeoDataFrame.from_features(feature_collection["features"], crs="EPSG:4326")

CRS operations

gdf = gdf.set_crs("EPSG:4326")          # 赋值 CRS(数据本身不变)
gdf = gdf.to_crs("EPSG:3857")           # 投影变换(坐标重算)
gdf = gdf.to_crs(epsg=32650)            # 按 EPSG 代码投影
utm = gdf.estimate_utm_crs()            # 自动检测 UTM 分区

Note:set_crs() only marks the CRS without transforming coordinates;to_crs() actually performs coordinate transformation. Before area/distance calculations, be sure to project to an appropriate projected coordinate system (such as UTM).

Spatial analysis

# 空间连接
joined = gpd.sjoin(points_gdf, polygons_gdf, how="inner", predicate="within")

# 最近邻连接
nearest = gpd.sjoin_nearest(gdf1, gdf2, max_distance=1000, distance_col="dist_m")

# 空间叠加
result = gpd.overlay(gdf1, gdf2, how="intersection")

# 裁剪
clipped = gpd.clip(gdf, mask_polygon)
clipped = gpd.clip(gdf, (xmin, ymin, xmax, ymax))  # 矩形快速裁剪

# 按属性融合
dissolved = gdf.dissolve(by="province", aggfunc="sum")

# 多部件炸开
exploded = gdf.explode(index_parts=False)

# 缓冲区、简化
gdf["buffer_100m"] = gdf.geometry.buffer(100)
gdf["simplified"] = gdf.geometry.simplify(tolerance=50)

Geometric predicates and measures

gdf.geometry.intersects(other_geom)    # Series[bool]
gdf.geometry.contains(other_geom)      # Series[bool]
gdf.geometry.within(other_geom)        # Series[bool]
gdf.geometry.distance(other_geom)      # Series[float]
gdf.geometry.area                      # Series[float]
gdf.geometry.length                    # Series[float]
gdf.geometry.centroid                  # GeoSeries
gdf.geometry.bounds                    # DataFrame
gdf.total_bounds                       # array [minx, miny, maxx, maxy]

Data output

gdf.to_file("output.gpkg", driver="GPKG", layer="result")
gdf.to_file("output.geojson", driver="GeoJSON")
gdf.to_parquet("output.parquet")
geojson_str = gdf.to_json()
gdf.to_postgis("table_name", engine, if_exists="replace")

Visualization

# 静态地图
ax = gdf.plot(column="population", cmap="YlOrRd", legend=True, figsize=(12, 8))

# 多图层叠加
ax = base_gdf.plot(color="lightgrey", figsize=(12, 8))
points_gdf.plot(ax=ax, color="red", markersize=5)

# 交互式地图
m = gdf.explore(column="population", cmap="viridis",
                tooltip=["name", "population"], tiles="CartoDB positron")

Common errors and solutions

Problem Cause Solution
Area/distance is 0 or extremely small CRS is a geographic coordinate system (degrees) gdf.to_crs(gdf.estimate_utm_crs()) compute after
sjoin returns no results The CRS of the two GDFs is inconsistent Unify CRS:gdf2 = gdf2.to_crs(gdf1.crs)
ValueError: GeoDataFrame does not support multiple columns using the geometry column name 'geometry' Multiple columns named geometry Rename conflicting columns or use set_geometry() to specify
to_file attribute is truncated Shapefile field name limit of 10 characters Use GeoPackage (.gpkg) or GeoJSON
set_crs vs to_crs confusion set_crs only assigns without transforming To transform an existing CRS, use to_crs(); to mark a missing CRS, use set_crs()
Shapefile does not support null values/datetime Shapefile format limitation Use the GeoPackage format
DriverError cannot be written Driver not supported or file is in use Check driver name spelling, close already opened files
align=True causes unexpected NaN Binary operations align by index by default Pass align=False or reset the index

Performance tips

  • GeoParquet is 5-10 times faster for reading and writing than Shapefile/GeoJSON; prefer using it
  • Spatial indexing .sindex automatically builds an STRtree,query() and nearest() can greatly accelerate spatial queries
  • Rectangular clipping clip_by_rect() or clip(gdf, (xmin,ymin,xmax,ymax)) is faster than polygon clipping
  • pyogrio engine(default) is 2-5 times faster than fiona 2-5x faster
  • For large datasets, use read_file(rows=slice(0, 1000)) to preview first
  • dissolve() Use method="coverage" is faster for polygons known to be non-overlapping
  • Avoid row-by-row looping over geometry operations; use vectorized methods (such as buffer(), intersection() , etc.)