地理空间数据库GeoPandas
概要
地理空间数据分析在许多领域中都有着广泛的应用,包括地理信息系统(GIS)、城市规划、环境科学、地质勘探等。Python GeoPandas是一个强大的库,旨在简化地理空间数据的处理和分析。本文将深入介绍GeoPandas库,包括其基本概念、功能特性、示例代码以及在实际应用中的应用场景。
一、什么是GeoPandas?
GeoPandas是一个开源的Python库,用于处理地理空间数据。它结合了两个其他流行的地理空间库,即Pandas和Shapely,提供了一个统一的数据结构来处理地理空间数据。GeoPandas的核心数据结构是GeoDataFrame,它是Pandas DataFrame的扩展,允许存储地理空间几何图形和属性数据。geopandas主要结合了pandas和shapely框架的能力。
- shapely 有一个名为 geometry 的类,也是python 中一个非常重要的类库,其中包含不同的几何对象。
- geopandas两个主要的数据结构,分别是GeoSeries和GeoDataFrame,分别对应了pandas中Series和DataFrame的子类。
- geopandas有三个基本类的几何对象(实际上是形状对象):点/点集合、 线/线集合、 多边形/多边形集合。
GeoPandas的主要功能包括:
- 读取和写入多种地理空间数据格式,如Shapefile、GeoJSON、PostGIS、KML等。
- 支持地理空间几何图形的创建、编辑和分析,包括点、线、面等。
- 提供空间连接、缓冲区分析、几何运算等地理空间操作。
- 具备数据可视化能力,可以绘制地理空间数据的地图。
二、安装GeoPandas
要开始使用GeoPandas,首先需要安装它。可以使用pip来安装GeoPandas及其依赖项:
pip install geopandas
安装完成后,可以在Python项目中引入GeoPandas并开始使用。
三、基本概念
3.1.GeoDataFrame
GeoPandas的核心数据结构是GeoDataFrame,它类似于Pandas的DataFrame,但包括一个额外的"geometry"列,用于存储地理空间几何图形。一个GeoDataFrame可以包含多个地理要素,每个要素具有一个几何图形和一组属性。以下是一个示例,展示了如何创建一个GeoDataFrame:
import geopandas as gpd from shapely.geometry import Point # 创建一个空的GeoDataFrame并指定几何列 gdf = gpd.GeoDataFrame(geometry=gpd.GeoSeries()) # 添加Point几何对象和属性数据 gdf['geometry'] = [Point(0, 0), Point(1, 1)] gdf['name'] = ['Point A', 'Point B'] # 显式设置几何列,显式设置geometry列为GeoDataFrame的几何列,以确保GeoDataFrame正确识别几何数据。 gdf = gdf.set_geometry('geometry') print(gdf)
上面的代码演示了如何使用GeoPandas库来创建和操作地理空间数据。具体来说,它展示了如何创建一个GeoDataFrame,向其中添加点几何对象和相关属性,并设置几何列。
3.2.几何图形
GeoPandas支持各种地理空间几何图形,包括点、线、面、多边形等。这些几何图形可以用来表示地理空间对象,如城市、河流、国家边界等。以下是一个示例,展示了如何创建不同类型的几何图形:
import geopandas as gpd from shapely.geometry import Point, LineString, Polygon # 创建几何对象 """ (1, 1):这个点的坐标。通常,坐标是以 (x, y) 的形式表示,其中 x 是横坐标,y 是纵坐标。在地理空间数据中,x 和 y 分别对应于经度和纬度,或者在平面坐标系中对应于水平和垂直位置。 意义:表示一个具体的位置。例如,一个城市的具体位置、一个传感器的放置点等 """ point = Point(1, 1) # 创建一个点 """ [(2, 0), (2, 4), (3, 4)]:这是一组有序的坐标点列表。每个点的坐标以 (x, y) 的形式表示。 意义:这些点按顺序连接形成一条线。表示线性地理对象,例如河流、道路、轨道等。 """ line = LineString([(2, 0), (2, 4), (3, 4)]) # 创建一条线 """ [(0, 0), (1, 0), (1, 1), (0, 1)]:这是一组有序的坐标点列表,定义多边形的顶点。第一个点和最后一个点通常是相同的,以闭合多边形。 意义:这些点按顺序连接形成一个闭合的区域。表示区域性地理对象,例如湖泊、国家边界、建筑轮廓等。 """ polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) # 创建一个多边形 # 创建一个包含几何对象的GeoDataFrame gdf = gpd.GeoDataFrame(geometry=[point, line, polygon]) # 添加属性数据 gdf['name'] = ['Point', 'Line', 'Polygon'] # 输出GeoDataFrame以查看其内容 print(gdf)
这些坐标数据是几何对象的基础,定义了对象在空间中的位置和形状:
- 点 (Point):单个坐标点,表示一个具体位置。
- 线 (LineString):由一系列坐标点按顺序连接形成的线,表示线性地理对象。
- 多边形 (Polygon):由一系列坐标点按顺序连接形成的闭合区域,表示面状地理对象
3.3.投影
地理空间数据通常需要投影到平面坐标系,以进行空间分析。GeoPandas支持各种地图投影,可以在需要时进行投影变换。以下是一个示例,展示了如何将GeoDataFrame投影到指定的投影坐标系:
import geopandas as gpd from shapely.geometry import Point, LineString, Polygon # 创建几何对象 point = Point(1, 1) # 创建一个点对象,坐标为(1, 1) line = LineString([(2, 0), (2, 4), (3, 4)]) # 创建一个线对象,包含一系列坐标点 polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) # 创建一个多边形对象,包含一系列坐标点,形成一个闭合区域 # 创建一个包含几何对象的GeoDataFrame,并指定初始坐标系 (WGS84, EPSG:4326) # geometry 参数指定几何数据,crs 参数指定坐标参考系统(Coordinate Reference System) gdf = gpd.GeoDataFrame(geometry=[point, line, polygon], crs="EPSG:4326") # 添加属性数据 # 创建一个新列 'name',分别给点、线、多边形对象赋予名称 gdf['name'] = ['Point', 'Line', 'Polygon'] # 输出初始GeoDataFrame及其坐标系 # 使用 print 函数输出 GeoDataFrame 的内容和初始坐标系信息 print("Initial GeoDataFrame:") print(gdf) print("\nInitial CRS:", gdf.crs) # 将GeoDataFrame投影到新的坐标系 (Mercator, EPSG:3857) # to_crs 方法用于将 GeoDataFrame 的坐标系从一个 CRS 转换到另一个 CRS # EPSG:4326 是 WGS84 地理坐标系,EPSG:3857 是 Web Mercator 投影坐标系 gdf_projected = gdf.to_crs("EPSG:3857") # 输出投影后的GeoDataFrame及其坐标系 # 使用 print 函数输出投影后的 GeoDataFrame 的内容和新坐标系信息 print("\nProjected GeoDataFrame:") print(gdf_projected) #输出投影后的GeoDataFrame的内容。 print("\nProjected CRS:", gdf_projected.crs) # 输出投影后的坐标参考系统 (CRS) 信息
四、基本用法
下面代码的主要目的是创建一个包含点、线和多边形几何对象的GeoDataFrame,并将其保存为Shapefile文件,以便进行地理空间数据的存储和后续处理。创建数据:
import geopandas as gpd # 导入GeoPandas库,用于处理地理空间数据 from shapely.geometry import Point, LineString, Polygon # 导入Shapely库中的几何对象类,用于创建几何对象 # 创建点几何对象,每个点由一对坐标 (x, y) 表示 points = [Point(1, 1), Point(2, 2), Point(3, 3)] # 创建线几何对象,每条线由一组坐标点 (x, y) 组成,表示线的节点 lines = [ LineString([(2, 0), (2, 4), (3, 4)]), # 第一条线,有三个节点 LineString([(0, 0), (1, 1), (1, 2)]) # 第二条线,有三个节点 ] # 创建多边形几何对象,每个多边形由一组坐标点 (x, y) 组成,表示多边形的顶点 polygons = [ Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]), # 第一个多边形,有四个顶点 Polygon([(2, 2), (3, 2), (3, 3), (2, 3)]) # 第二个多边形,有四个顶点 ] # 创建包含点几何对象的GeoDataFrame,并指定初始坐标系 (WGS84, EPSG:4326) # GeoDataFrame是一个特殊的DataFrame,专门用于处理地理空间数据 gdf_points = gpd.GeoDataFrame(geometry=points, crs="EPSG:4326") # 添加属性列 'name',为每个点几何对象命名 gdf_points['name'] = ['Point1', 'Point2', 'Point3'] # 添加属性列 'value',为每个点几何对象赋予一个数值 gdf_points['value'] = [10, 20, 30] # 创建包含线几何对象的GeoDataFrame,并指定初始坐标系 (WGS84, EPSG:4326) gdf_lines = gpd.GeoDataFrame(geometry=lines, crs="EPSG:4326") # 添加属性列 'name',为每条线几何对象命名 gdf_lines['name'] = ['Line1', 'Line2'] # 添加属性列 'value',为每条线几何对象赋予一个数值 gdf_lines['value'] = [100, 200] # 创建包含多边形几何对象的GeoDataFrame,并指定初始坐标系 (WGS84, EPSG:4326) gdf_polygons = gpd.GeoDataFrame(geometry=polygons, crs="EPSG:4326") # 添加属性列 'name',为每个多边形几何对象命名 gdf_polygons['name'] = ['Polygon1', 'Polygon2'] # 添加属性列 'value',为每个多边形几何对象赋予一个数值 gdf_polygons['value'] = [1000, 2000] # 定义保存Shapefile文件的路径 shapefile_path_points = 'points.shp' # 保存点几何对象的Shapefile路径 shapefile_path_lines = 'lines.shp' # 保存线几何对象的Shapefile路径 shapefile_path_polygons = 'polygons.shp' # 保存多边形几何对象的Shapefile路径 # 将包含点几何对象的GeoDataFrame保存为Shapefile文件 gdf_points.to_file(shapefile_path_points) # 将包含线几何对象的GeoDataFrame保存为Shapefile文件 gdf_lines.to_file(shapefile_path_lines) # 将包含多边形几何对象的GeoDataFrame保存为Shapefile文件 gdf_polygons.to_file(shapefile_path_polygons) # 输出保存路径,确认文件已保存 print(f"Shapefile已保存到: {shapefile_path_points}, {shapefile_path_lines}, {shapefile_path_polygons}")
4.1.读取地理空间数据
GeoPandas可以轻松读取多种地理空间数据格式。要读取 polygons.shp 文件的内容,可以使用GeoPandas的 read_file 函数。以下是逐行添加注释的代码示例,展示了如何读取并打印 polygons.shp 文件的内容:
import geopandas as gpd # 导入GeoPandas库,用于处理地理空间数据 # 定义Shapefile文件的路径 shapefile_path_polygons = 'polygons.shp' # 保存多边形几何对象的Shapefile路径 # 读取Shapefile文件,创建GeoDataFrame gdf_polygons = gpd.read_file(shapefile_path_polygons) # 输出GeoDataFrame的内容 print("读取的GeoDataFrame内容:") print(gdf_polygons) # 输出GeoDataFrame的坐标系 print("\nGeoDataFrame的坐标系:") print(gdf_polygons.crs)
4.2.空间操作
GeoPandas提供了丰富的空间操作功能,可以执行各种地理空间分析。以下是一些示例操作:
- 计算两个地理空间对象的交集:
intersection = gdf1.intersection(gdf2)
计算地理空间
- 对象的缓冲区:
buffered = gdf.buffer(distance=100)
- 计算地理空间对象之间的距离:
distance = gdf1.distance(gdf2)
- 判断一个地理空间对象是否包含另一个对象:
contains = gdf1.contains(gdf2)
案例代码如下:
import geopandas as gpd # 导入GeoPandas库,用于处理地理空间数据 from shapely.geometry import Point, Polygon # 导入Shapely库中的几何对象类,用于创建几何对象 """ 创建示例几何对象 Polygon([(x1, y1), (x2, y2), ...]):创建多边形几何对象,由一组顶点坐标点组成。 Point(x, y):创建点几何对象,由一对坐标 (x, y) 表示。 """ polygon1 = Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]) # 第一个多边形 polygon2 = Polygon([(1, 1), (3, 1), (3, 3), (1, 3)]) # 第二个多边形 point = Point(1, 1) # 一个点 # 创建包含几何对象的GeoDataFrame # gpd.GeoDataFrame(geometry=[几何对象], crs="EPSG:4326"):创建包含几何对象的GeoDataFrame,并指定初始坐标系为WGS84(EPSG:4326)。 gdf1 = gpd.GeoDataFrame(geometry=[polygon1], crs="EPSG:4326") gdf2 = gpd.GeoDataFrame(geometry=[polygon2], crs="EPSG:4326") gdf_point = gpd.GeoDataFrame(geometry=[point], crs="EPSG:4326") # 计算两个地理空间对象的交集 # gdf1.overlay(gdf2, how='intersection'):计算两个GeoDataFrame的交集,并创建一个新的GeoDataFrame。 intersection = gdf1.overlay(gdf2, how='intersection') print("两个多边形的交集:") print(intersection) # 计算地理空间对象的缓冲区 buffered = gdf1.buffer(distance=0.5) # 计算第一个多边形的缓冲区,缓冲距离为0.5单位。 print("\n第一个多边形的缓冲区:") print(buffered) # 计算地理空间对象之间的距离 distance = gdf1.distance(gdf_point) # gdf1.distance(gdf_point):计算第一个多边形与点之间的距离。 print("\n第一个多边形与点之间的距离:") print(distance) # 判断一个地理空间对象是否包含另一个对象 contains = gdf1.contains(gdf_point) print("\n第一个多边形是否包含点:") print(contains)
4.3.数据可视化
GeoPandas具备数据可视化功能,可以绘制地理空间数据的地图。以下是一个示例,展示如何绘制GeoDataFrame的地图:
pip install matplotlib -i https://mirrors.aliyun.com/pypi/simple/
案例代码:
import geopandas as gpd # 导入GeoPandas库,用于处理和可视化地理空间数据 import matplotlib.pyplot as plt # 导入Matplotlib库,用于创建图形和绘图 # 创建示例几何对象 from shapely.geometry import Point, LineString, Polygon # 导入Shapely库中的几何对象类,用于创建几何对象 # 创建几何对象 point = Point(1, 1) # 创建一个点对象 line = LineString([(2, 0), (2, 4), (3, 4)]) # 创建一条线对象 polygon = Polygon([(0, 0), (1, 0), (1, 1), (0, 1)]) # 创建一个多边形对象 # 创建包含几何对象的GeoDataFrame,并指定初始坐标系 (WGS84, EPSG:4326) gdf = gpd.GeoDataFrame(geometry=[point, line, polygon], crs="EPSG:4326") # 添加属性数据 gdf['name'] = ['Point', 'Line', 'Polygon'] gdf['value'] = [10, 20, 30] # 绘制GeoDataFrame的地图 gdf.plot() # 使用GeoDataFrame的plot方法绘制地图 # 显示绘制的地图 plt.show() # 使用Matplotlib的show方法显示图形
实现效果如下:

在这个示例中,使用plot方法绘制了GeoDataFrame的地图,并使用Matplotlib进行显示。
五、功能特性
5.1.空间连接
GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系进行连接。这对于分析地理空间数据之间的关联非常有用。以下是一个示例,展示如何执行空间连接:
import geopandas as gpd # 导入GeoPandas库,用于处理和可视化地理空间数据 from shapely.geometry import Point, Polygon # 导入Shapely库中的几何对象类,用于创建几何对象 # 创建第一个GeoDataFrame,包含一些点 gdf_points = gpd.GeoDataFrame({ 'id': [1, 2, 3], # 'id'列表示每个点的唯一标识符 'geometry': [Point(1, 1), Point(2, 2), Point(3, 3)] # 'geometry'列包含点的几何对象 }, crs="EPSG:4326") # 创建一个包含点的GeoDataFrame,并指定坐标系为WGS84(EPSG:4326) # 创建第二个GeoDataFrame,包含一些多边形 gdf_polygons = gpd.GeoDataFrame({ 'id': ['A', 'B'], # 'id'列表示每个多边形的唯一标识符 'geometry': [Polygon([(0, 0), (2, 0), (2, 2), (0, 2)]), Polygon([(2, 2), (4, 2), (4, 4), (2, 4)])] # 'geometry'列包含多边形的几何对象 }, crs="EPSG:4326") # 创建一个包含多边形的GeoDataFrame,并指定坐标系为WGS84(EPSG:4326) # 执行空间连接操作,将点GeoDataFrame与多边形GeoDataFrame进行空间连接 joined_gdf = gpd.sjoin(gdf_points, gdf_polygons, how="inner", predicate="within") # 'gpd.sjoin' 函数用于进行空间连接操作 # 'gdf_points' 是第一个GeoDataFrame,包含点 # 'gdf_polygons' 是第二个GeoDataFrame,包含多边形 # 'how="inner"' 表示使用内连接,只保留在两个GeoDataFrame中都存在的几何对象 # 'predicate="within"' 表示空间关系为点在多边形内部 # 输出空间连接结果 print(joined_gdf) # 打印连接后的GeoDataFrame
5.2.空间缓冲区分析
GeoPandas可以执行空间缓冲区分析,用于分析地理空间对象的邻近关系。可以计算一个地理空间对象的缓冲区,以确定其周围的特定距离范围内有哪些其他对象。以下是一个示例,展示如何计算地理空间对象的缓冲区:
# 计算地理空间对象的缓冲区 buffered = gdf.buffer(distance=100)
完整案例代码如下:
import geopandas as gpd # 导入GeoPandas库,用于处理和可视化地理空间数据 from shapely.geometry import Point, Polygon # 导入Shapely库中的几何对象类,用于创建几何对象 # 创建一个GeoDataFrame,包含一些点 gdf = gpd.GeoDataFrame({ 'id': [1, 2, 3], # 'id'列表示每个点的唯一标识符 'geometry': [Point(1, 1), Point(2, 2), Point(3, 3)] # 'geometry'列包含点的几何对象 }, crs="EPSG:4326") # 创建一个包含点的GeoDataFrame,并指定坐标系为WGS84(EPSG:4326) # 计算每个点的缓冲区,距离为1单位 gdf['buffer'] = gdf.geometry.buffer(1) # 'buffer' 函数用于计算几何对象的缓冲区 # '1' 表示缓冲区的距离,单位与几何对象的坐标系一致 # 输出包含缓冲区的GeoDataFrame print(gdf) # 绘制原始点和缓冲区 ax = gdf.plot(color='blue', edgecolor='black') # 绘制点 gdf.set_geometry('buffer').plot(ax=ax, color='red', alpha=0.5, edgecolor='black') # 绘制缓冲区 plt.show() # 显示绘制的地图
效果如下:

但是会报错:

这个警告是因为在地理坐标系(经纬度)中执行缓冲区计算会导致不准确的结果。为了解决这个问题,我们需要将数据投影到平面坐标系,然后进行缓冲区计算。下面是修改后的代码,它将GeoDataFrame投影到Mercator坐标系(EPSG:3857)进行缓冲区计算,然后再将其投影回原来的地理坐标系:
import geopandas as gpd # 导入GeoPandas库,用于处理和可视化地理空间数据 from shapely.geometry import Point # 导入Shapely库中的几何对象类,用于创建几何对象 import matplotlib.pyplot as plt # 导入Matplotlib库,用于绘制图形 # 创建一个GeoDataFrame,包含一些点 gdf = gpd.GeoDataFrame({ 'id': [1, 2, 3], # 'id'列表示每个点的唯一标识符 'geometry': [Point(1, 1), Point(2, 2), Point(3, 3)] # 'geometry'列包含点的几何对象 }, crs="EPSG:4326") # 创建一个包含点的GeoDataFrame,并指定坐标系为WGS84(EPSG:4326) # 将GeoDataFrame从地理坐标系(WGS84)投影到一个平面坐标系(Mercator, EPSG:3857) gdf_projected = gdf.to_crs("EPSG:3857") # 计算每个点的缓冲区,距离为1000米(因为Mercator坐标系的单位是米) gdf_projected['buffer'] = gdf_projected.geometry.buffer(1000) # 将GeoDataFrame投影回地理坐标系(WGS84) gdf_buffered = gdf_projected.to_crs("EPSG:4326") # 输出包含缓冲区的GeoDataFrame print(gdf_buffered) # 绘制原始点和缓冲区 ax = gdf.plot(color='blue', edgecolor='black') # 绘制原始点 gdf_buffered.set_geometry('buffer').plot(ax=ax, color='red', alpha=0.5, edgecolor='black') # 绘制缓冲区 plt.show() # 显示绘制的地图
如下:

5.3.数据可视化
GeoPandas内置了数据可视化功能,可以绘制各种地理空间数据的地图。可以自定义地图样式、添加标签和图例等。
示例:绘制地理空间数据的地图,并自定义样式、添加标签和图例
import geopandas as gpd # 导入GeoPandas库,用于处理和可视化地理空间数据 from shapely.geometry import Point # 导入Shapely库中的几何对象类,用于创建几何对象 import matplotlib.pyplot as plt # 导入Matplotlib库,用于绘制图形 from matplotlib.patches import Patch # 导入Patch类,用于自定义图例 # 创建一个GeoDataFrame,包含一些点 gdf = gpd.GeoDataFrame({ 'id': [1, 2, 3], # 'id'列表示每个点的唯一标识符 'name': ['Point 1', 'Point 2', 'Point 3'], # 'name'列表示点的名称 'geometry': [Point(1, 1), Point(2, 2), Point(3, 3)] # 'geometry'列包含点的几何对象 }, crs="EPSG:4326") # 创建一个包含点的GeoDataFrame,并指定坐标系为WGS84(EPSG:4326) # 将GeoDataFrame从地理坐标系(WGS84)投影到一个平面坐标系(Mercator, EPSG:3857) gdf_projected = gdf.to_crs("EPSG:3857") # 计算每个点的缓冲区,距离为1000米(因为Mercator坐标系的单位是米) gdf_projected['buffer'] = gdf_projected.geometry.buffer(1000) # 将GeoDataFrame投影回地理坐标系(WGS84) gdf_buffered = gdf_projected.to_crs("EPSG:4326") # 创建一个Matplotlib的子图 fig, ax = plt.subplots() # 自定义地图样式:设置点的颜色(青色)、边界线颜色(黑色)和线宽 gdf.plot(ax=ax, color='cyan', edgecolor='black', markersize=100, linewidth=1, label='Original Points') # 绘制缓冲区,设置缓冲区的颜色(黄色)、边界线颜色(红色)、透明度和线宽 gdf_buffered.set_geometry('buffer').plot(ax=ax, color='yellow', alpha=0.5, edgecolor='red', linewidth=2, label='Buffer Zones') # 添加标签 for x, y, label in zip(gdf.geometry.x, gdf.geometry.y, gdf['name']): ax.text(x, y, label, fontsize=12, ha='right') # 在每个点旁边添加标签,字体大小为12,水平对齐方式为右对齐 # 自定义图例处理器,设置图例项的颜色和标签 handles = [Patch(color='cyan', label='Original Points'), Patch(color='yellow', alpha=0.5, edgecolor='red', label='Buffer Zones')] # 添加图例 plt.legend(handles=handles) # 设置图标题 plt.title('Custom Styled Geospatial Data Visualization with Buffers') # 显示绘制的地图 plt.show()
该代码将生成一个包含点和缓冲区的地图。点以青色显示,缓冲区以黄色半透明显示,并有红色边界线。地图中添加了每个点的标签和自定义的图例。

浙公网安备 33010602011771号