GeoPandas官方快速入门文档(中文翻译版)
原文链接>>Introduction to GeoPandas
点这里可以一键跑通>>GeoPandas 简介
本快速教程介绍了GeoPandas的主要概念和基本功能,以帮助您开始编写您的项目。
GeoPandas,顾名思义,通过增加对地理空间数据的支持,扩展了流行的数据科学库pandas 如果你对 pandas不熟悉,我们建议在继续之前快速浏览一下它的快速入门文档。
GeoPandas的核心数据结构是geopandas.GeoDataFrame,它是pandas.DataFrame的子类,可以存储几何列并执行空间操作。geopandas.GeoSeries是pandas.Series的一个子类,处理几何图形。因此,你的GeoDataFrame是pandas.Series和geopandas.GeoSeries的组合,前者是传统数据(数字、布尔值、文本等),后者是几何图形(点、多边形等)。你可以按照你的意愿拥有任意多的几何列;没有典型的桌面GIS软件的限制。
每个 GeoSeries可以包含任何几何体类型(你甚至可以在一个数组中混合它们),并且有一个GeoSeries.crs属性,它存储了关于投影的信息(CRS代表坐标参考系统)。因此,GeoDataFrame中的每个GeoSeries都可以使用不同的投影,例如,允许你对同一个几何体有多个版本(不同的投影)。
一个 GeoDataFrame中只有一个GeoSeries被认为是 active 的几何体,这意味着所有应用于 GeoDataFrame的几何操作都在这个 active 列上操作。
首先,我们需要读取一些数据。
假设你有一个包含数据和几何体的文件(例如GeoPackage、GeoJSON、Shapefile),你可以使用geopandas.read_file()来读取它,它会自动检测文件类型并创建一个GeoDataFrame。本教程使用 "nybb"数据集,这是一张纽约各区的地图,是GeoPandas安装的一部分。因此,我们使用geopandas.datasets.get_path()来检索该数据集的路径。
import geopandas
path_to_data = geopandas.datasets.get_path("nybb")
gdf = geopandas.read_file(path_to_data)
gdf
使用GeoDataFrame.to_file()将GeoDataFrame写回文件。默认的文件格式是Shapefile,但你可以用driver关键字指定你自己的文件格式。
gdf.to_file("my_file.geojson", driver="GeoJSON")
现在我们有了 GeoDataFrame,可以开始处理它的几何图形。
由于在纽约区的数据集中只有一列几何体,这一列自动成为 active 的几何体,在GeoDataFrame上使用的空间方法将应用于 "geometry"列。
要测量每个多边形(或本例中的MultiPolygon)的面积,请访问GeoDataFrame.area属性,它返回一个pandas.Series。注意,GeoDataFrame.area只是GeoSeries.area应用于 active 的几何列。
但首先,为了使结果更容易阅读,将各区的名称设置为索引:
gdf = gdf.set_index("BoroName")
gdf["area"] = gdf.area
gdf["area"]
要获得每个多边形的边界(LineString),请访问GeoDataFrame.boundary。
gdf['boundary'] = gdf.boundary
gdf['boundary']
由于我们已经将边界保存为一个新的列,我们现在在同一个GeoDataFrame中有两个几何列。
我们还可以创建新的几何体,例如,可以是原始几何体的缓冲版本(即GeoDataFrame.buffer(10))或其中心点。
gdf['centroid'] = gdf.centroid
gdf['centroid']
我们还可以测量每个中心点离第一个中心点的距离。
first_point = gdf['centroid'].iloc[0]
gdf['distance'] = gdf['centroid'].distance(first_point)
gdf['distance']
注意geopandas.GeoDataFrame是pandas.DataFrame的子类,所以我们有所有的pandas功能可用于地理空间数据集 — 我们甚至可以对属性和几何信息一起进行数据操作。
例如,要计算上面测量的距离的平均值,可以访问 "距离 "列并对其调用 mean() 方法:
gdf['distance'].mean() # output: 76140.09102166798
GeoPandas也可以绘制地图,因此我们可以检查几何体在空间中的表现。要绘制活动的几何图形,请调用GeoDataFrame.plot()。要按另一列进行颜色编码,请将该列作为第一个参数传入。在下面的例子中,我们绘制了活动几何体列,并按 "面积 "列进行颜色编码。我们还想显示一个图例(legend=True)。
gdf.plot("area", legend=True)
你也可以使用GeoDataFrame.explore()交互式地探索你的数据,其行为与plot()相同,但会返回一个交互式地图。
# 复现时出错 AttributeError: 'CRS' object has no attribute 'equals'
# 待官方完善
# gdf.explore("area", legend=False)
将活动的几何图形(GeoDataFrame.set_geometry)转换为中心点,我们可以用点的几何图形绘制相同的数据。
gdf = gdf.set_geometry("centroid")
gdf.plot("area", legend=True)
我们也可以将两个GeoSeries分层在彼此之上。我们只需要把一个作为另一个的画布。
ax = gdf["geometry"].plot()
gdf["centroid"].plot(ax=ax, color="black")
现在我们把活动的几何体设置回原来的GeoSeries。
gdf = gdf.set_geometry("geometry")
我们可以进一步处理几何体,并在已有的几何体的基础上创建新的形状。
如果我们对多边形的凸壳感兴趣,我们可以访问GeoDataFrame.convex_hull。
gdf["convex_hull"] = gdf.convex_hull
ax = gdf["convex_hull"].plot(alpha=.5) # 将第一个图保存为ax,并将alpha(透明度)设置为0.5
gdf["boundary"].plot(ax=ax, color="white", linewidth=.5) # 传递第一幅图,并将linewitdth设置为0.5
在其他情况下,我们可能需要使用GeoDataFrame.buffer()对几何体进行缓冲。几何方法会自动应用于活动的几何体,但我们也可以直接应用于任何GeoSeries。让我们来缓冲各区和它们的中心点,并将它们绘制在彼此的上面。
# 缓冲10000英尺的活动几何体(几何体已经以英尺为单位)
gdf["buffered"] = gdf.buffer(10000)
# 缓冲10000英尺的几何体(几何体已经以英尺为单位)
gdf["buffered_centroid"] = gdf["centroid"].buffer(10000)
ax = gdf["buffered"].plot(alpha=.5) # 将第一个图保存为ax,并将alpha(透明度)设置为0.5
gdf["buffered_centroid"].plot(ax=ax, color="red", alpha=.5) # 将第一幅图作为画布传递给第二幅图
gdf["boundary"].plot(ax=ax, color="white", linewidth=.5) # 传递第一幅图,并将linewitdth设置为0.5
我们还可以询问不同几何体的空间关系。使用上面的几何图形,我们可以检查哪些缓冲区与布鲁克林的原始几何图形相交,即与布鲁克林相距10 000英尺以内。
首先,我们得到一个布鲁克林的多边形。
brooklyn = gdf.loc["Brooklyn", "geometry"]
brooklyn
多边形是一个shapely geometry object,与GeoPandas中使用的任何其他几何图形一样。
type(brooklyn) # output: shapely.geometry.multipolygon.MultiPolygon
然后我们可以检查gdf[“buffered”]中的哪些几何图形与之相交。
gdf["buffered"].intersects(brooklyn)
只有布朗克斯(在北部)与布鲁克林的距离超过10 000英尺。其他的都比较近,与我们的多边形相交。
另外,我们可以检查哪些缓冲中心点完全在原始区的多边形内。在这种情况下,两个GeoSeries都被对齐,并对每一行进行检查。
gdf["within"] = gdf["buffered_centroid"].within(gdf)
gdf["within"]
我们可以将结果绘制在地图上,以确认这一发现。
gdf = gdf.set_geometry("buffered_centroid")
ax = gdf.plot("within", legend=True, categorical=True, legend_kwds={'loc': "upper left"}) # 使用分类图并设置图例的位置
gdf["boundary"].plot(ax=ax, color="black", linewidth=.5) # 传递第一幅图,并将linewitdth设置为0.5
每个GeoSeries都有其坐标参考系统(CRS),可在 GeoSeries.crs中访问。CRS告诉GeoPandas这些几何图形的坐标在地球表面的位置。在某些情况下,CRS是地理的,这意味着坐标是经纬度的。在这些情况下,其CRS是WGS84,授权代码为EPSG:4326。让我们看看我们的纽约市各区GeoDataFrame的投影。
gdf.crs
Geometries在EPSG:2263中,坐标为英尺。我们可以使用GeoSeries.to_crs()轻松地将GeoSeries重新投射到另一个CRS,如EPSG:4326。
gdf = gdf.set_geometry("geometry")
boroughs_4326 = gdf.to_crs("EPSG:4326")
boroughs_4326.plot()
boroughs_4326.crs
请注意沿图中轴线的坐标差异。以前我们有120 000 - 280 000(英尺),现在有40.5 - 40.9(度)。在这种情况下,boroughs_4326有一个WGS84的 "geometry"列,但所有其他的(包括中心点等)仍然在原来的CRS中。
对于依赖距离或面积的操作,你需要使用投影CRS(米、英尺、公里等)而不是地理CRS(度)。GeoPandas操作是平面的,而度数反映的是球体上的位置。因此,使用度的空间操作可能不会产生正确的结果。例如,gdf.area.sum()(投影CRS)的结果是8 429 911 572英尺,但boroughs_4326.area.sum()(地理CRS)的结果是0.083。