跳至主要内容

GeoPandas 教程:地理空间分析入门

开始使用 GeoPandas,这是一款最受欢迎的 Python 地理空间分析库之一。
· 15分钟 阅读

使用 AI 探索

我们每天生成的大量数据本质上都具有空间属性。从地球观测数据、GPS 数据到各种地图中的数据,空间数据(有时也称为地理空间数据或地理信息)指的是每条记录都关联了一个特定位置的数据。

每一个空间数据点都可以在地图上定位。这通常通过某种坐标参考系来实现,例如地理坐标,也就是我们常用的纬度-经度对,用于指定地球上某物体的位置。这样我们就能够观察数据之间的空间关系。

然而,地理空间数据的真正力量在于同时结合数据本身及其位置,从而解锁更复杂的分析机会。所谓地理空间数据科学是数据科学的一个分支领域,专注于利用空间算法和分析技术(如机器学习和深度学习)从地理空间数据中提取信息。换句话说,地理空间数据科学帮助我们理解事件发生在哪里,以及为什么会发生在那里。

有许多适用于地理空间数据科学的工具。本教程将聚焦 GeoPandas,这是一款在 Python 中处理地理空间数据的开源包。

GeoPandas 扩展了 pandas 使用的数据类型(pandas 是 Python 中处理数据框的标准工具),以便对几何类型执行空间操作。由于 GeoPandas 构建于 pandas 之上(以及其他流行的数据科学 Python 包,如 matplotlib),因此使用 Python 的数据专业人士可以很容易上手 GeoPandas 的语法。

安装 Python GeoPandas

要使用 Python 的 GeoPandas,首先需要像安装其他 Python 库一样安装它。

需要注意的是,GeoPandas 依赖一整套开源地理空间库来发挥其完整的空间能力,包括 shapely、fiona、pyproj 和 rtree。您必须确保安装了这些依赖项,否则 GeoPandas 可能无法按预期工作。

为避免复杂性,GeoPandas 建议使用 conda 包管理器安装该库。这意味着您需要先安装 Anaconda。关于如何安装和使用 Anaconda的指南,请参阅我们的教程。

使用 conda 的优势在于,它为所有操作系统(Windows、Mac、Linux)提供了 GeoPandas 所需及可选依赖项的预编译二进制包。要在命令行中安装 GeoPandas:

>>conda install geopandas

或者,您也可以使用 Python 的标准包安装工具 pip 来安装 Anaconda。如前所述,您同样需要安装必要的依赖项。如果您不熟悉 pip,我们强烈建议阅读我们的 Pip 包管理教程。使用 pip 安装 GeoPandas 的命令为:

>>pip install geopandas 

无论哪种方式,如果在安装 GeoPandas 的过程中遇到问题,请查阅其文档获取更多信息。

安装完成后,您就可以开始使用 GeoPandas 了。只需在 Python 环境中导入它。请注意,常见的导入方式是使用别名 gpd。

import geopandas as gpd

GeoPandas 的基础操作

本节将介绍您可以用 GeoPandas 完成的最基本操作。在此过程中,我们也会引入地理空间分析中的一些关键概念,包括空间数据类型、空间数据格式和坐标参考系(CRS)。

读取与写入空间数据

就像 pandas 需要输入数据以转换为 pandas 数据框一样,GeoPandas 读取输入(空间)数据并将其转换为所谓的 GeoDataFrame。

在介绍 GeoPandas 可读取的多种空间文件类型之前,首先需要区分不同类型的空间数据。我们所处理的数据类型会决定应使用哪些工具来分析并可视化数据。

基本上,空间数据主要有两种类型:

  1. 矢量数据。它通过离散几何体来描述地球上地理位置的要素,主要包括:
    • 点。单个位置,例如一栋建筑或一辆车,具有 X 和 Y 坐标。
    • 线。由一系列连接的点构成,描述道路或河流等。
    • 多边形。由封闭的线围成一个区域,例如国家边界。此外,当一个要素由多个几何体组成时,我们称之为 MultiPolygon(多多边形)。
  2. 栅格数据。将世界编码为由网格表示的连续表面,类似图像的像素。网格中的每个单元可以是连续值(如海拔)或分类值(如土地覆盖类型)。经典示例包括高程数据或卫星影像。

Raster Data

来源:Humboldt State University

矢量和栅格数据通常都伴随有非空间数据,也称为属性。空间数据可以包含任意数量的附加属性,用于补充位置相关信息。例如,一所学校的位置可以关联学校名称、学生人数或地址等。

GeoPandas 旨在处理矢量数据,不过它也可以与其他 Python 包(如 rasterio)配合,轻松处理栅格数据。为读取空间数据,GeoPandas 提供了 geopandas.read_file() 函数。该强大的函数可以自动读取大多数常见的基于矢量的空间数据。

一些最常见的矢量数据格式包括:

  • Shapefile。作为行业标准,Shapefile 是最常见的矢量数据格式。它由三个文件组成,通常以 zip 文件打包提供:
      • .shp 文件包含图形几何体。
      • .dbf 文件保存每个几何体的属性,
      • .shx 文件(形状索引文件)帮助将属性与形状关联。
  • GeoJSON。这是 2016 年发布的一种较新的地理空间数据格式。与 Shapefile 不同,GeoJSON 是单一文件,更易于使用。

在接下来的示例中,我们将使用 geopandas.read_file() 函数读取一个托管在 GitHub 的 GeoJSON 文件,其中包含巴塞罗那市不同行政区的地理空间数据。

url = 'https://raw.githubusercontent.com/jcanalesluna/bcn-geodata/master/districtes/districtes.geojson'

districts = gpd.read_file(url)

districts

Barcelona District Data

我们稍后会回到该数据集,但首先,您需要了解如何将 GeoDataFrame 写回到文件。这非常简单。只需使用 GeoDataFrame.to_file() 创建一个包含空间数据的文件。默认情况下,新文件的格式为 Shapefile,但您可以通过“driver”参数进行更改。

例如,您可以将行政区 GeoDataFrame 保存为一个 geoJSON 文件:

districts.to_file("districts.geojson", driver="GeoJSON")

探索 GeoDataFrame

您可能已经注意到,上一节中的 GeoDataFrame 与传统的 pandas 数据框很相似。这并不奇怪,因为 GeoDataFrame 是 pandas.DataFrame 的子类。这意味着它继承了许多 pandas 数据框的方法和属性。GeoDataFrame 的新特性在于它可以存储几何列(也称 GeoSeries)并执行空间操作。

几何列可以包含任何类型的矢量数据,如点、线和多边形。此外,需要注意的是,尽管一个 GeoDataFrame 可以具有多个 GeoSeries,但只有一列被视为活动几何列,这意味着所有空间操作都将基于该列进行。

GeoDataFrame

来源:GeoPandas

GeoDataFrame 的另一个重要特性是每个 GeoSeries 都带有关联的 CRS 信息。CRS 信息告诉 GeoPandas 这些坐标在地球上的位置。该信息对于空间分析至关重要。例如,如果您需要合并两个空间数据集,就必须确保它们使用相同的 CRS,否则将无法获得预期结果。

CRS 主要分为两大类:

  • 地理坐标。以相对于赤道和本初子午线的经纬度(度)来定义全球位置。借助该系统,我们可以轻松指定地球上的任意位置。它被广泛应用,例如在 GPS 中。最常用的 CRS 是 EPSG:4326,也称为 WGS84。
  • 投影坐标。 虽然地球是球体,但我们通常在二维地图上表示它。投影坐标以 X 和 Y 维度表示位置,从而使我们能够使用米等长度单位而非度数进行工作,这使分析更为便捷有效。然而,将三维地球转换到二维地图不可避免会产生畸变。这就是为什么存在不同的投影坐标构建方法。例如,许多国家为其特定地理环境采用了标准的投影 CRS。

关于 CRS 还有更多内容,但这超出了本教程范围。获取更多信息和实践示例的优质资源是我们的《在 Python 中处理地理空间数据》课程。

在 GeoPandas 中,CRS 信息存储在 crs 属性中:

districts.crs

Geopandas CRS

目前该行政区 GeoDataFrame 关联的是地理坐标(EPSG: 4326),但我们希望将其转换为投影坐标,以便用米进行计算。让我们将其转换为 EPSG:2062,即西班牙的标准投影 CRS。可使用 Geopandas.to_crs() 方法完成。

districts.to_crs(epsg=2062, inplace=True)

districts.crs

Geopandas_to_crs

现在我们已经设置了合适的投影 CRS,可以开始探索 GeoDataFrame 的属性了。

探索空间数据集的属性

GeoPandas 继承了 shapely 包中的许多实用方法和属性。我们将介绍其中四个。

面积

area 属性返回几何体的计算面积。我们可以将计算得到的面积(换算为平方千米)存入一个新列:

districts['area'] = districts.area / 1000000

districts

Districts With Area

质心

centroid 属性返回几何体的中心点。我们可以将其添加到数据集中,从而创建一个新的几何列。

districts['centroid']=districts.centroid

districts

Districts With Centroid

边界

boundary 属性返回多边形的边界线。

districts['boundary']=districts.boundary

距离

distance 方法给出某几何体到某位置的最小距离。假设我们想要计算著名的圣家堂(位于 Eixample 区)到巴塞罗那各区中心点的距离,并将距离(千米)添加到新列中。

Sagrada Familia

圣家堂。来源:Wikipedia

首先,我们需要使用 shapely 的 Point() 函数根据所需坐标(可在 Google 地图中轻松获取)创建一个点,将其转换为具有正确 CRS 的 GeoSeries,然后使用 GeoPandas.distance() 方法:

from shapely.geometry import Point

sagrada_fam = Point(2.1743680500855005, 41.403656946781304)
sagrada_fam = gpd.GeoSeries(sagrada_fam, crs=4326)
sagrada_fam= sagrada_fam.to_crs(epsg=2062)
districts['sagrada_fam_dist'] = [float(sagrada_fam.distance(centroid)) / 1000 for centroid in districts.centroid]

经过上述空间操作后,得到的数据集如下所示:

spatial operations

使用 GeoPandas 绘图

我们所做的空间操作为研究提供了有价值的信息。然而,将几何体可视化到空间上是改进分析的绝佳方式。幸运的是,使用 GeoPandas 绘图非常简单。只需调用基于 Python 的 matplotlib 包构建的 GeoDataFrame.plot() 函数即可。

让我们从巴塞罗那各区的基础可视化开始。

ax= districts.plot(figsize=(10,6))

Barcelona Districts Basic
我们可以通过为每个行政区着色来让 GeoPandas 图更具信息量。将图例设置为 'True' 会创建图例,帮助解释颜色。

ax= districts.plot(column=district_name', figsize=(10,6), edgecolor='black', legend=True)

Barcelona Districts Colour

最后,我们可以在地图上添加各行政区的中心点和圣家堂,并加上标题。同样地,为使图表更具吸引力,我们可以使用优秀的 contextily 包,为图表添加巴塞罗那城市的底图切片。

import contextily
ax= districts.plot(column='district_name', figsize=(12,6), alpha=0.5, legend=True)
districts["centroid"].plot(ax=ax, color="green")
sagrada_fam.plot(ax=ax,color='black', marker='+')
contextily.add_basemap(ax, crs=districts.crs.to_string())
plt.title('A Beautiful Map of Barcelona')
plt.axis('off')
plt.show()

Map of Barcelona

很酷,对吧?关于如何制作精美的空间可视化,还有很多可做之事。我们的课程 用 Python 可视化地理空间数据 是提升您可视化技能的绝佳资源。

使用 GeoPandas 处理空间关系

地理空间数据的关键方面之一是它们在空间中的相互关系。GeoPandas 借助 pandas 和 shapely 的强大功能,能够在空间数据集之间执行各种空间关系操作。本节我们将介绍一些最常见的操作。

属性连接

在 pandas 中合并数据集有两种方式:属性连接和空间连接。

属性连接允许我们基于非几何变量将两个 GeoDataFrame 进行连接,就像在 pandas 中的常规连接一样。事实上,执行属性连接的方式就是使用标准的 pandas.merge() 方法。如果您想进一步了解 pandas 的连接操作,请查看我们的pandas 数据框连接教程。

例如,将 2022 年巴塞罗那的人口数据丰富到我们的 GeoDataFrame 中就很有意义。

pop =pd.read_csv('poblacion_barna_2022.csv', usecols=['Nom_Districte','Nombre'])
pop = pd.DataFrame(pop.groupby('Nom_Districte')['Nombre'].sum()).reset_index()
pop.columns=['district_name','population_22']
districts = districts.merge(pop)
districtsv

Barcelona Population Data

空间连接

相比之下,空间连接允许基于空间关系合并两个 GeoDataFrame。

例如,让我们识别巴塞罗那的 自行车道位于哪些行政区。

url = 'https://opendata-ajuntament.barcelona.cat/resources/bcn/CarrilsBici/CARRIL_BICI.geojson'
bike_lane = gpd.read_file(url)
bike_lane = bike_lane.loc[:,['ID','geometry']]
bike_lane.to_crs(epsg=2062, inplace=True)

ID and Geometry

Barcelona Bike Lanes

在 GeoPandas 中,空间连接操作通过 sjoin() 函数提供。第一个参数是我们希望添加信息的 GeoDataFrame,第二个参数是包含要添加信息的 GeoDataFrame。然后,我们需要指定连接类型。最后,“predicate” 参数告诉 GeoPandas 用哪种空间关系来匹配两个数据集。常见的关系包括 “intersects”(相交)、“contains”(包含)和 “within”(位于内部)。

在我们的示例中,我们将使用谓词 “intersects”。如果两个几何对象具有任何边界或内部点相同,则它们相交。

lanes_districts = gpd.sjoin(districts, bike_lane, how='inner', predicate='intersects')
lanes_districts

Intersects

请注意,结果 GeoDataFrame 的行数比 bike_lane GeoDataFrame 多。这是因为一条自行车道可能位于多个行政区中。

最后,我们可以对数据集进行分组,获取各行政区的自行车道数量:

lanes_districts.groupby('district_name').size()

Lanes Groupby

GeoPandas 叠加操作

最后,空间叠加允许您比较两个包含多边形或多多边形几何体的 GeoDataFrame,并创建一个新的 GeoDataFrame,其中的新几何体代表空间上的组合以及合并后的属性。下图展示了不同的可能性:

Multipolygon Gemometry

来源:GeoPandas

设想巴塞罗那市政府为了应对污染并促进社区健康,计划建设新的本地公园。一个初步想法是在每个行政区中心 500 米范围内建设大型的圆形公园。我们可以通过基于每个行政区的质心创建缓冲区来模拟这一方案。

parks = gpd.GeoDataFrame(districts.centroid.buffer(500), geometry=0)

parks.plot()

centroid of every district

现在,我们可以进行一些叠加操作了。例如,如果我们只想查看公园将要落地的各行政区区域,可以使用 GeoPandas.overlay() 方法:

parks_intersection = districts.overlay(parks, how='intersection')
ax = parks_intersection.plot(alpha=0.5, edgecolor='black', column='district_name')

Geopandas Overlay

或者,如果我们想查看去除拟建公园占用区域后的行政区范围,可以更改 “how” 参数来执行另一种叠加操作。

parks_difference = districts.overlay(parks, how='difference')
ax = parks_difference.plot(alpha=0.5, edgecolor='black', column='district_name')

Geopandas Overlay 2

结语

希望您喜欢这篇 GeoPandas 教程。空间分析是数据科学中最酷的领域之一,为通过位置数据丰富分析提供了无限机会。用于空间分析的工具有很多,但如果您已经熟悉 Python,GeoPandas 会是一个极好的起点。

还想继续深化您的地理空间学习?我们已经为您准备好了!查看以下资料,成为地理空间高手:

GeoPandas 常见问题

什么是地理空间数据分析?

地理空间数据科学是数据科学的一个分支领域,专注于利用空间算法和分析技术从地理空间数据中提取信息。

什么是 GeoPandas?

GeoPandas 是一个开源项目,旨在让在 Python 中处理地理空间数据变得更简单。

pandas 与 GeoPandas 有何区别?

GeoPandas 扩展了 pandas 使用的数据类型,使其能够对几何类型执行空间操作。GeoPandas 使用 pandas 的 DataFrame 来创建所谓的 GeoDataFrame。

作为 R 程序员,我如何学习空间分析?

除了 Python 课程之外,DataCamp 还为 R 程序员提供了大量的空间相关课程和学习路径。

主题