Geopandas 是一个用于处理地理空间数据的 Python 库,结合了 pandas
的数据处理能力和shapely、fiona
等库的地理空间操作功能,添加了对几何对象的支持。以下是一些 Geopandas 常用属性和方法:
一、常见API属性
1. GeoDataFrame
GeoDataFrame
是 GeoPandas 的核心数据结构,类似于 pandas 的DataFrame
,但它多了一列GeoSeries
,包含了地理空间数据(通常是点、线或多边形),当然GeoDataFrame也可以拥有任意数量的GeoSeries列。- 常见的属性:
gdf.crs
:获取或设置坐标参考系统(Coordinate Reference System,CRS)。gdf.geometry
:包含几何数据的列(通常是Point
、LineString
或Polygon
)。gdf.bounds
:获取每个几何对象的边界框(最小矩形)坐标。gdf.shape
:返回 GeoDataFrame 的行列数。gdf.columns
:返回数据框的列名。
2. 几何对象
Point
、LineString
、Polygon
等对象是常见的几何数据类型。gdf.geometry
列通常包含这些几何对象,Geopandas 使用这些对象进行空间操作。- 几何对象的方法:
.area
:计算几何对象的面积。.length
:计算几何对象的长度(适用于LineString
)。.centroid
:计算几何对象的中心点。.distance(other_geometry)
:计算当前几何对象与另一个几何对象之间的距离。.intersects(other_geometry)
:检查当前几何对象是否与另一个几何对象相交。
3. 空间操作
gdf.plot()
:绘制地图,显示几何数据。gdf.to_crs()
:转换坐标参考系统。gdf.clip()
:裁剪几何数据,保留指定范围内的数据。gdf.sjoin()
:空间连接,允许在不同 GeoDataFrame 之间根据空间关系连接数据。
4. 读取与写入数据
geopandas.read_file()
:读取地理数据文件(如 Shapefile、GeoJSON、PostGIS 等)。gdf.to_file()
:将 GeoDataFrame 写入文件,如shapefile
或GeoJSON
。
下面是一个详细的 GeoPandas 入门教程,涵盖了从数据加载、处理到可视化的常用操作。
二、初级用法
1. 安装 GeoPandas
如自动安装失败,可手动安装。参考:https://blog.csdn.net/qq_35240689/article/details/123900570?fromshare=blogdetail&sharetype=blogdetail&sharerId=123900570&sharerefer=PC&sharesource=qq_35240689&sharefrom=from_link
pip install geopandas
2. 导入必要的库
import geopandas as gpd
import matplotlib.pyplot as plt
3. 读取地理数据文件
- GeoPandas 支持多种地理数据格式,例如
Shapefile、GeoJSON、PostGIS
等。以下是如何读取一个 Shapefile 文件的示例:
# 读取 Shapefile 数据文件
gdf = gpd.read_file("path_to_your_file.shp")
# 查看数据的前几行
print(gdf.head())
# 如果是 `GeoJSON` 格式的文件,可以类似地读取:
gdf = gpd.read_file("path_to_your_file.geojson")
4. 检查坐标参考系统(CRS)
- 每个地理数据都有一个坐标参考系统,GeoPandas 可以读取并处理这些坐标系统。
# 获取坐标参考系统
print(gdf.crs)
- 如果你想设置一个新的 CRS,可以使用
to_crs()
方法:
# 将 CRS 转换为 WGS84(经纬度坐标系)
gdf = gdf.to_crs(epsg=4326)
- 将 file2 文件的坐标参考系统转成 file1
gdf1 = gpd.read_file("file1.shp")
gdf2 = gpd.read_file("file2.shp")
if(gdf1.crs):
gdf2 = gdf2.to_crs(gdf1.crs)
5. 几何数据操作
- GeoPandas 允许你对几何数据进行多种操作,例如计算
面积 geometry.area、长度 geometry.length、中心点 geometry.centroid
等。
# 计算每个几何对象的面积
gdf['area'] = gdf.geometry.area
# 计算每个几何对象的长度(适用于 LineString)
gdf['length'] = gdf.geometry.length
# 计算每个几何对象的中心点
gdf['centroid'] = gdf.geometry.centroid
6. 绘制地理数据
- GeoPandas 提供了简单的绘图接口,帮助可视化地理数据。
# 绘制地图
gdf.plot()
# 显示地图
plt.show()
- 还可以定制图形的外观,比如设置颜色、边框等:
gdf.plot(color='lightblue', edgecolor='black')
# 设置标题和标签
plt.title("Geospatial Data Plot")
plt.xlabel("Longitude")
plt.ylabel("Latitude")
# 显示图像
plt.show()
7. 计算几何对象之间的空间关系
GeoPandas 提供了一些方法来进行空间查询。例如:算两个几何对象之间的距离
geometry.distance
计算两个几何对象之间的距离geometry.intersects
检查一个多边形是否包含另一个点。
# 假设我们有一个点 geometry 对象 `point`
point = gpd.GeoSeries([Point(1, 1)])
# 计算点与地理数据中所有多边形之间的距离
gdf['distance'] = gdf.geometry.distance(point)
# 检查点是否与每个多边形相交
gdf['intersects'] = gdf.geometry.intersects(point)
8. 空间连接(Spatial Join)
-
GeoPandas 允许你根据空间关系将两个 GeoDataFrame 连接在一起。例如,查找某些点是否落在多边形区域内。参数解释
-
how : 合并方式,合并后以哪边为主,可选参数
inner、left、right
,默认inner
只保留有空间关系的行 -
predicate :空间关系判断条件(旧版的参数
op
已弃用),可选值:- intersects:相交(默认)、
- contains:包含、
- within:被包含、
- touches:接触、
- crosses:交叉、
- overlaps:重叠、
- covers:覆盖、
- covered_by:被覆盖
- contains_properly:严格包含
-
lsuffix:合并后左侧 DataFrame 列名冲突时添加的后缀,默认加
left
-
Rsuffix:合并后右侧 DataFrame 列名冲突时添加的后缀,默认加
right
-
distance:指定缓冲距离(与原始几何体的距离),用于扩展空间关系判断范围
-
on_attribute:最大允许距离,用于限制空间关系的最大距离
gpd.sjoin(left_df, right_df, how='inner', predicate='intersects',
lsuffix='left', rsuffix='right', distance=None, max_distance=None)
9. 裁剪(Clipping)
- clip() 是 GeoPandas 中最直接的裁剪方法,用于用一个几何对象裁剪另一个 GeoDataFrame。
- gdf (必需)要被裁剪的 GeoDataFrame
- mask (必需) 用于裁剪的几何对象,可以是:GeoDataFrame、GeoSeries 和 shapely 几何对象 (Polygon/MultiPolygon)
- keep_geom_type (可选,默认为 True)。如果为 True,裁剪后保留原始几何类型;如果为 False,可能生成混合几何类型的集合
# 假设我们有一个多边形区域 `mask`,它代表我们想保留的区域
mask= gpd.GeoSeries([Polygon([(-1, 1), (-1, 2), (1, 2), (1, 1)])])
# 使用裁剪操作
gpd.clip(gdf, mask, keep_geom_type=True)
cx
按矩形边界框裁剪
clipped = gdf.cx[minx:maxx, miny:maxy]
gpd.overlay()
方法也可以实现裁剪,具体在高级用法中。
10. 保存数据
- GeoPandas 支持将修改后的地理数据保存为新的文件格式:
# 保存为新的 Shapefile 文件
gdf.to_file("output_file.shp")
# 或者保存为 GeoJSON 格式
gdf.to_file("output_file.geojson", driver="GeoJSON")
11. 进阶:基于地理数据进行空间分析——数据处理
# 计算点的密度(适用于点数据)
gdf['density'] = gdf.geometry.apply(lambda geom: geom.area / geom.length if geom.is_valid else 0)
三、高级用法
1. unary_union
unary_union
可以将一个 GeoDataFrame 中的所有几何对象合并成一个单一的几何对象。这个方法对于处理多个多边形合并为一个多边形非常有用。是空间分析中的"一元合并"操作,能够自动处理几何间的重叠部分,比迭代使用 union() 更高效。(旧版函数 cascaded_union 已弃用)
# 合并所有多边形为一个单一的几何对象
districts = gpd.read_file('districts.shp')
province = districts.geometry.unary_union
# 这将返回一个单一的多边形或多几何对象(如果它们不相交)
print(province)
2. 缓冲区分析 buffer
buffer() 是 GeoPandas/Shapely 中用于创建几何缓冲区的重要空间分析方法,可以为点、线、面几何对象创建指定距离的缓冲区区域,是进行区域扩展
或设置安全区的有力工具。
-
distance
(必需)缓冲区距离,单位与几何对象的坐标参考系统(CRS)一致。正数:向外扩展;负数:向内收缩(仅对多边形有效)。可以是单个数值或数组(为每个几何设置不同距离)
-
- resolution (可选,默认16),控制缓冲区边界的平滑度(近似圆的边数),值越大越平滑但计算量越大。例如:4=菱形,8=八边形,16=近似圆(默认)
-
- cap_style (可选,默认1),线端点的缓冲样式:
- 1 = CAP_STYLE.round (圆形端点,默认)
- 2 = CAP_STYLE.flat (平头端点)
- 3 = CAP_STYLE.square (方形端点)
-
- join_style (可选,默认1),线拐角处的连接样式:
- 1 = JOIN_STYLE.round (圆角连接,默认)
- 2 = JOIN_STYLE.mitre (尖角连接)
- 3 = JOIN_STYLE.bevel (斜角连接)
-
- mitre_limit (可选,默认5.0),当使用尖角连接(mitre)时的最大比例限制,防止过长的尖角出现,仅当 join_style=JOIN_STYLE.mitre 时有效
# 返回一个新的GeoSeries,包含所有缓冲后的多边形几何(原始几何类型会被转换为多边形(MultiPolygon))
gdf.geometry.buffer(distance, resolution=16, cap_style=1, join_style=1, mitre_limit=5.0)
gdf['buffer'] = gdf.geometry.buffer(1) # 创建半径为1的缓冲区 是缓冲区的大小
- 注意:
buffer
方法生成的几何类型与输入几何的类型相同
。如果输入是多边形,则输出也是多边形。如果输入是点,则输出将是一个圆形缓冲区。
3. apply
与 geometry.apply
apply
方法允许你对 GeoDataFrame 中的每个几何对象执行自定义的空间操作,特别是在需要根据每个几何的特定属性进行处理时。
# 使用 apply 对每个几何对象应用自定义的函数
def custom_function(geometry):
# 例如,计算每个多边形的周长与面积之比
if geometry.geom_type == 'Polygon':
return geometry.length / geometry.area
return 0
gdf['custom_ratio'] = gdf.geometry.apply(custom_function)
print(gdf.head())
这种方法可以非常灵活地与其他几何属性配合使用。
4. dissolve
dissolve
方法允许你基于某一列的值合并几何对象。这对于根据特定类别(例如州、城市、区域等)对数据进行聚合时非常有用。
# 基于某列(如 'region')的值合并几何对象
gdf_dissolved = gdf.dissolve(by='region')
# 聚合后的 GeoDataFrame 中每个区域将由一个多边形表示
print(gdf_dissolved.head())
# 等价于
grouped = gdf.groupby('region').agg({'geometry': lambda x: unary_union(x)})
5. geopandas.tools
模块
geopandas.tools
模块包含一些实用的工具函数,例如geocode
(地理编码),可以将地址转换为经纬度坐标。
from geopandas.tools import geocode
# 使用 geocode 函数进行地理编码,获取某个地址的坐标
address = "1600 Pennsylvania Ave NW, Washington, DC 20500"
location = geocode(address)
print(location)
geocode
是一个用于地址解析的高级工具,可以将地址转换为点(经纬度坐标)。需要注意的是,这通常依赖于外部地理编码服务。
6. overlay
(空间重叠分析)
方法返回这两个数据集之间的交集、差集等。
how
参数可以选择intersection
(默认、交集)、union
(并集)、difference
(差集)或symmetric_difference
(对称差集)。- keep_geom_type (可选)。如果为 True,只保留与输入相同的几何类型;如果为 False,可能生成混合几何类型的集合
- make_valid (可选,默认为 True),是否自动修复无效几何
# 对两个 GeoDataFrame 执行空间重叠操作
gdf_overlay = gpd.overlay(gdf1, gdf2, how='intersection')
gpd.overlay(df1, df2, how='intersection', keep_geom_type=None, make_valid=True)
8. simplify
(简化几何)
simplify
方法用于简化几何图形对象用的重要函数,它可以减少几何图形的顶点数量,同时尽可能保持原始形状,尤其在处理大规模多边形时,可以有效减小数据量。
tolerance
参数决定简化的程度,较大的值将产生更粗略的简化效果。单位:与几何对象的坐标参考系统(CRS)一致地理CRS(如EPSG:4326):单位为度、投影CRS(如UTM):单位为米
- preserve_topology (可选,默认为True),保证简化后的几何是有效的(不会自相交);False:使用更快的算法,但可能产生无效几何
# 简化每个几何对象
gdf['simplified'] = gdf.geometry.simplify(tolerance=0.01)
# 绘制简化后的结果
gdf['simplified'].plot()
plt.show()
9. extent
(空间范围)
total_bounds
用于返回数据集的边界框(bounding box),通常用于地图缩放和裁剪bounds
用于返回单个几何对象的空间范围bounds['minx']
用于返回单列几何对象的所有空间范围,返回的也是一列数据
# 获取数据的边界范围
bbox= gdf.total_bounds
print(bbox) # 输出:[minx, miny, maxx, maxy]
# 单个几何对象的 extent
minx, miny, maxx, maxy = polygon.bounds
# 计算 GeoDataFrame 中每个几何对象的 extent
gdf['minx'] = gdf.geometry.bounds['minx']
gdf['miny'] = gdf.geometry.bounds['miny']
gdf['maxx'] = gdf.geometry.bounds['maxx']
gdf['maxy'] = gdf.geometry.bounds['maxy']
10. sjoin_nearest
(最近邻空间连接)
gpd.sjoin_nearest()
是 GeoPandas 中的 最近邻空间连接 方法,用于基于最近距离关系连接两个 GeoDataFrame。它比传统的 sjoin
更灵活,允许非接触的空间关系匹配。
- 核心参数
| 参数 | 类型 | 默认值 | 说明 |
|------|------|--------|------|
|left_df
| GeoDataFrame | - | 左数据集(保留几何列) |
|right_df
| GeoDataFrame | - | 右数据集 |
|how
| str | ‘inner’ | 连接方式:‘left’, ‘right’, ‘inner’ |
|max_distance
| float | None | 最大搜索距离(单位同CRS) |
|lsuffix
| str | ‘left’ | 左列名冲突后缀 |
|rsuffix
| str | ‘right’ | 右列名冲突后缀 |
|distance_col
| str | None | 存储距离的列名 |
|exclusive
| bool | False | 是否禁止一对多匹配 |
gpd.sjoin_nearest(left_df, right_df, how='inner', max_distance=None,
lsuffix='left', rsuffix='right', distance_col=None, exclusive=False)
# 基础最近邻匹配
gpd.sjoin_nearest(left_df, right_df, how='inner', distance_col='distance')
# 带距离限制的匹配
gpd.sjoin_nearest(left_df, right_df, max_distance=1000, distance_col='distance')
# 一对一无重复匹配
result = gpd.sjoin_nearest(
fire_stations,
accidents,
how='left',
exclusive=True # 确保一对一关系
)
# 检查匹配率
print(f"匹配率:{len(result)/len(left_df):.1%}")
# 查看距离分布
result['distance'].describe()
- 注意事项
-
CRS单位敏感,确保使用投影坐标系(单位是米),经纬度坐标(度单位)会导致距离计算错误
-
性能优化,构建空间索引加速查询 left_df.sindex、right_df.sindex
-
大数据集处理,考虑先进行空间筛选(如
cx
裁剪),分块处理大规模数据
- 与
sjoin
对比
特性 | sjoin | sjoin_nearest |
---|---|---|
空间关系 | 需指定(相交/包含等) | 自动计算最近邻 |
非接触匹配 | 不支持 | 支持 |
距离控制 | 无 | 可设max_distance |
距离记录 | 需额外计算 | 可直接存储 |
匹配方式 | 多对多 | 可设一对一 |
-
高级用法
- 自定义最近邻条件
# 先筛选再匹配(提高效率)
mask = clinics.geometry.intersects(patients.unary_union.buffer(5000))
filtered_clinics = clinics[mask]
result = gpd.sjoin_nearest(
patients,
filtered_clinics,
distance_col='distance'
)
- 多条件最近邻
# 结合属性过滤(如只匹配三甲医院)
result = (
patients
.sjoin_nearest(
clinics[clinics['level'] == '三甲'],
distance_col='distance'
)
)
11. distance
计算两几何对象之间的距离
# 计算两几何对象之间的距离
distance = gdf.ggeometry
gdf1.gdf.geometry.distance(gdf2)
# 计算两个GeoDataFrame间的距离矩阵
stores = gpd.read_file('stores.shp')
customers = gpd.read_file('customers.shp')
# 计算每个顾客到所有商店的距离
distance_matrix = customers.geometry.apply(
lambda cust_geom: stores.distance(cust_geom)