注意
GeoPandas简介#
这个快速教程介绍了GeoPandas的关键概念和基本特性,帮助您开始您的项目。
概念#
GeoPandas, 顾名思义,通过添加对地理空间数据的支持,扩展了流行的数据科学库 pandas。如果您不熟悉 pandas,我们建议在继续之前快速查看其 入门文档。
GeoPandas中的核心数据结构是geopandas.GeoDataFrame,它是pandas.DataFrame的子类,可以存储几何列并执行空间操作。geopandas.GeoSeries是pandas.Series的子类,处理几何形状。因此,您的GeoDataFrame是pandas.Series(传统数据,如数值、布尔、文本等)和geopandas.GeoSeries(几何形状,如点、多边形等)的组合。您可以根据需要拥有任意数量的几何列;与一些典型的桌面GIS软件不同。
每个 GeoSeries 可以包含任何几何类型(您甚至可以在一个数组中混合它们),并具有 GeoSeries.crs 属性,该属性存储有关投影的信息(CRS 代表坐标参考系统)。因此,每个 GeoSeries 在 GeoDataFrame 中可以使用不同的投影,这允许您拥有,例如,同一几何图形的多个版本(不同的投影)。
在一个 GeoDataFrame 中只有一个 GeoSeries 被认为是 活动几何列,这意味着对 GeoDataFrame 应用的所有几何操作都作用于这一列。活动几何列通过 GeoDataFrame.geometry 属性访问。
用户指南
在用户指南中查看更多有关 数据结构 的内容。
让我们看看这些概念在实践中是如何运作的。
读取和写入文件#
首先,我们需要读取一些数据。
读取文件#
假设您有一个包含数据和几何信息的文件(例如 GeoPackage、GeoJSON、Shapefile),您可以使用 geopandas.read_file() 来读取它,该函数会自动检测文件类型并创建一个 GeoDataFrame。本教程使用 "nybb" 数据集,这是一个纽约区的地图,可以通过 geodatasets 包获得。因此,我们使用 geodatasets.get_path() 来下载数据集并检索本地副本的路径。
[1]:
import geopandas
from geodatasets import get_path
path_to_data = get_path("nybb")
gdf = geopandas.read_file(path_to_data)
gdf
[1]:
| 行政区代码 | 行政区名称 | 形状长度 | 形状面积 | 几何 | |
|---|---|---|---|---|---|
| 0 | 5 | 史坦顿岛 | 330470.010332 | 1.623820e+09 | MULTIPOLYGON (((970217.022 145643.332, 970227.... |
| 1 | 4 | 皇后区 | 896344.047763 | 3.045213e+09 | MULTIPOLYGON (((1029606.077 156073.814, 102957... |
| 2 | 3 | 布鲁克林 | 741080.523166 | 1.937479e+09 | MULTIPOLYGON (((1021176.479 151374.797, 102100... |
| 3 | 1 | 曼哈顿 | 359299.096471 | 6.364715e+08 | 多边形 (((981219.056 188655.316, 980940.... |
| 4 | 2 | 布朗克斯 | 464392.991824 | 1.186925e+09 | MULTIPOLYGON (((1012821.806 229228.265, 101278... |
写入文件#
要将 GeoDataFrame 写回文件,使用 GeoDataFrame.to_file()。默认情况下,文件格式由文件扩展名推断(例如 .shp 用于 Shapefile, .geojson 用于 GeoJSON),但您可以通过 driver 关键字显式指定这一点。
[2]:
gdf.to_file("my_file.geojson", driver="GeoJSON")
用户指南
在用户指南中查看更多关于 读取和写入文件 的信息。
简单的访问器和方法#
现在我们有了我们的 GeoDataFrame,可以开始处理它的几何形状。
由于纽约区数据集中只有一个几何列,因此该列自动成为活动几何,应用于GeoDataFrame的空间方法将应用于"geometry"列。
测量面积#
要测量每个多边形(在这个特定情况下是MultiPolygon)的面积,可以访问 GeoDataFrame.area 属性,它返回一个 pandas.Series。请注意 GeoDataFrame.area 只是将 GeoSeries.area 应用于 active 几何列。
但是首先,为了使结果更易于阅读,将区的名称设置为索引:
[3]:
gdf = gdf.set_index("BoroName")
[4]:
gdf["area"] = gdf.area
gdf["area"]
[4]:
BoroName
Staten Island 1.623822e+09
Queens 3.045214e+09
Brooklyn 1.937478e+09
Manhattan 6.364712e+08
Bronx 1.186926e+09
Name: area, dtype: float64
获取多边形边界和中心点#
要获取每个多边形(线串)的边界,可以访问 GeoDataFrame.boundary:
[5]:
gdf["boundary"] = gdf.boundary
gdf["boundary"]
[5]:
BoroName
Staten Island MULTILINESTRING ((970217.022 145643.332, 97022...
Queens MULTILINESTRING ((1029606.077 156073.814, 1029...
Brooklyn MULTILINESTRING ((1021176.479 151374.797, 1021...
Manhattan MULTILINESTRING ((981219.056 188655.316, 98094...
Bronx MULTILINESTRING ((1012821.806 229228.265, 1012...
Name: boundary, dtype: geometry
由于我们将边界保存为一个新列,现在在同一个 GeoDataFrame中有两个几何列。
我们还可以创建新的几何形状,例如原始几何形状的缓冲区版本(即, GeoDataFrame.buffer(10))或它的中心点:
[6]:
gdf["centroid"] = gdf.centroid
gdf["centroid"]
[6]:
BoroName
Staten Island POINT (941639.45 150931.991)
Queens POINT (1034578.078 197116.604)
Brooklyn POINT (998769.115 174169.761)
Manhattan POINT (993336.965 222451.437)
Bronx POINT (1021174.79 249937.98)
Name: centroid, dtype: geometry
测量距离#
我们还可以测量每个中心点与第一个中心点位置的距离。
[7]:
first_point = gdf["centroid"].iloc[0]
gdf["distance"] = gdf["centroid"].distance(first_point)
gdf["distance"]
[7]:
BoroName
Staten Island 0.000000
Queens 103781.535276
Brooklyn 61674.893421
Manhattan 88247.742789
Bronx 126996.283623
Name: distance, dtype: float64
请注意,geopandas.GeoDataFrame 是 pandas.DataFrame 的子类, 因此我们可以在地理空间数据集上使用所有的 pandas 功能——我们甚至可以结合属性和几何信息进行数据操作。
例如,要计算上述测量的距离的平均值,可以访问“distance”列并在其上调用mean()方法:
[8]:
gdf["distance"].mean()
[8]:
np.float64(76140.09102166798)
制作地图#
GeoPandas 还可以绘制地图,因此我们可以检查几何体在空间中的样子。要绘制活动几何体,请调用 GeoDataFrame.plot()。要按另一个列进行着色编码,请将该列作为第一个参数传入。在下面的示例中,我们绘制活动几何体列,并按 "area" 列进行着色编码。我们还想显示图例 (legend=True)。
[9]:
gdf.plot("area", legend=True)
[9]:
<Axes: >
您还可以使用 GeoDataFrame.explore() 以交互方式探索您的数据,它的行为与 plot() 相同,但返回的是一个交互式地图。
[10]:
gdf.explore("area", legend=False)
[10]:
将活动几何形状 (GeoDataFrame.set_geometry) 切换为重心,我们可以使用点几何形状绘制相同的数据。
[11]:
gdf = gdf.set_geometry("centroid")
gdf.plot("area", legend=True)
[11]:
<Axes: >
我们还可以将两个 GeoSeries 叠加在一起。我们只需使用一个图作为另一个的轴。
[12]:
ax = gdf["geometry"].plot()
gdf["centroid"].plot(ax=ax, color="black")
[12]:
<Axes: >
现在我们将活动几何形状设置回原始 GeoSeries。
[13]:
gdf = gdf.set_geometry("geometry")
用户指南
在用户指南中查看更多关于 映射 的内容。
几何体创建#
我们可以进一步处理几何形状,并基于已有的形状创建新的形状。
凸包#
如果我们对多边形的凸包感兴趣,我们可以访问 GeoDataFrame.convex_hull。
[14]:
gdf["convex_hull"] = gdf.convex_hull
[15]:
# saving the first plot as an axis and setting alpha (transparency) to 0.5
ax = gdf["convex_hull"].plot(alpha=0.5)
# passing the first plot and setting linewidth to 0.5
gdf["boundary"].plot(ax=ax, color="white", linewidth=0.5)
[15]:
<Axes: >
缓冲区#
在其他情况下,我们可能需要使用 GeoDataFrame.buffer() 对几何体进行缓冲。几何方法会自动应用于当前活动几何体,但我们也可以直接对任何 GeoSeries 应用它们。让我们对各个行政区及其质心进行缓冲,并将两者重叠绘制。
[16]:
# buffering the active geometry by 10 000 feet (geometry is already in feet)
gdf["buffered"] = gdf.buffer(10000)
# buffering the centroid geometry by 10 000 feet (geometry is already in feet)
gdf["buffered_centroid"] = gdf["centroid"].buffer(10000)
[17]:
# saving the first plot as an axis and setting alpha (transparency) to 0.5
ax = gdf["buffered"].plot(alpha=0.5)
# passing the first plot as an axis to the second
gdf["buffered_centroid"].plot(ax=ax, color="red", alpha=0.5)
# passing the first plot and setting linewidth to 0.5
gdf["boundary"].plot(ax=ax, color="white", linewidth=0.5)
[17]:
<Axes: >
用户指南
在用户指南中查看更多关于 几何操作 的信息。
几何关系#
我们还可以询问不同几何图形的空间关系。使用上面的几何图形,我们可以检查哪些缓冲区的区与原始的布鲁克林几何相交,即,距离布鲁克林在10,000英尺以内。
首先,我们获得布鲁克林的一个多边形。
[18]:
brooklyn = gdf.loc["Brooklyn", "geometry"]
brooklyn
[18]:
多边形是一个 shapely 几何对象,与 GeoPandas 中使用的其他几何形状相同。
[19]:
type(brooklyn)
[19]:
shapely.geometry.multipolygon.MultiPolygon
然后我们可以检查gdf["buffered"]中的哪些几何图形与之相交。
[20]:
gdf["buffered"].intersects(brooklyn)
[20]:
BoroName
Staten Island True
Queens True
Brooklyn True
Manhattan True
Bronx False
dtype: bool
只有布朗克斯(在北部)距离布鲁克林超过 10,000 英尺。其他的都更近并且与我们的多边形相交。
或者,我们可以检查哪些缓冲质心完全位于原始区的多边形内。在这种情况下,两个 GeoSeries 是对齐的,并且检查是在每一行上进行的。
[21]:
gdf["within"] = gdf["buffered_centroid"].within(gdf)
gdf["within"]
[21]:
BoroName
Staten Island True
Queens True
Brooklyn False
Manhattan False
Bronx False
Name: within, dtype: bool
我们可以在地图上绘制结果以确认发现。
[22]:
gdf = gdf.set_geometry("buffered_centroid")
# using categorical plot and setting the position of the legend
ax = gdf.plot(
"within", legend=True, categorical=True, legend_kwds={"loc": "upper left"}
)
# passing the first plot and setting linewidth to 0.5
gdf["boundary"].plot(ax=ax, color="black", linewidth=0.5)
[22]:
<Axes: >
投影#
每个 GeoSeries 都可以通过 GeoSeries.crs 访问其坐标参考系统 (CRS)。CRS 告诉 GeoPandas 几何体的坐标在地球表面的哪个位置。在某些情况下,CRS 是地理的,这意味着坐标是以经度和纬度表示的。在这些情况下,它的 CRS 是 WGS84,权限代码 EPSG:4326。让我们看看我们纽约区的 GeoDataFrame 的投影。
[23]:
gdf.crs
[23]:
<Projected CRS: EPSG:2263>
Name: NAD83 / New York Long Island (ftUS)
Axis Info [cartesian]:
- X[east]: Easting (US survey foot)
- Y[north]: Northing (US survey foot)
Area of Use:
- name: United States (USA) - New York - counties of Bronx; Kings; Nassau; New York; Queens; Richmond; Suffolk.
- bounds: (-74.26, 40.47, -71.8, 41.3)
Coordinate Operation:
- name: SPCS83 New York Long Island zone (US survey foot)
- method: Lambert Conic Conformal (2SP)
Datum: North American Datum 1983
- Ellipsoid: GRS 1980
- Prime Meridian: Greenwich
几何图形在 EPSG:2263 中,坐标以英尺为单位。我们可以轻松地将 GeoSeries 重新投影到另一个坐标参考系统,如 EPSG:4326,使用 GeoSeries.to_crs()。
[24]:
gdf = gdf.set_geometry("geometry")
boroughs_4326 = gdf.to_crs("EPSG:4326")
boroughs_4326.plot()
[24]:
<Axes: >
[25]:
boroughs_4326.crs
[25]:
<Geographic 2D CRS: EPSG:4326>
Name: WGS 84
Axis Info [ellipsoidal]:
- Lat[north]: Geodetic latitude (degree)
- Lon[east]: Geodetic longitude (degree)
Area of Use:
- name: World.
- bounds: (-180.0, -90.0, 180.0, 90.0)
Datum: World Geodetic System 1984 ensemble
- Ellipsoid: WGS 84
- Prime Meridian: Greenwich
注意到图表坐标轴上的差异。之前我们有 120 000 - 280 000(英尺),现在我们有 40.5 - 40.9(度)。在这种情况下,boroughs_4326 在 WGS84 中具有 "geometry" 列,但所有其他(包括质心等)仍保留在原始 CRS 中。
警告
对于依赖于距离或面积的操作,您始终需要使用投影坐标参考系统(以米、英尺、公里等为单位),而不是地理坐标参考系统(以度为单位)。GeoPandas 操作是平面的,而度数反映的是球体上的位置。因此,使用度数的空间操作可能无法产生正确的结果。例如,gdf.area.sum()(投影坐标参考系统)的结果是 8 429 911 572 ft2,但 boroughs_4326.area.sum()(地理坐标参考系统)的结果是 0.083。
用户指南
在用户指南中查看更多关于 投影 的信息。
接下来做什么?#
使用GeoPandas,我们可以做更多的事情,比到目前为止介绍的内容还要多,从 聚合,到 空间连接,再到 地理编码,以及 更多其他。
前往用户指南以了解有关GeoPandas的不同功能的更多信息,查看示例以了解它们如何使用,或查看API参考以获取详细信息。