Fiona读取地理数据?与GeoPandas啥区别?

GIS基础理论
Dr.GIS
wowwwai GIS研习社 · 工具流程与项目排障

很多同学在做 Python GIS 数据处理时会搜索“Fiona读取地理数据?与GeoPandas啥区别?”,因为两者都能打开 Shapefile、GeoPackage、GeoJSON 等矢量数据,但写法、返回对象和适用场景并不一样。简单说:Fiona 更像“底层矢量数据读写接口”,GeoPandas 更像“带空间能力的表格分析工具”。

本文以一个常见任务为主线:用 Python 读取一个行政区划 Shapefile,查看属性、筛选要素、保存结果,并解释什么时候应该用 Fiona,什么时候应该用 GeoPandas。

Fiona读取地理数据与GeoPandas读取矢量数据区别示意图
Fiona 和 GeoPandas 都能读取矢量数据,但一个偏底层读写,一个偏空间表格分析。

引言:先看一个最小可运行例子

假设你有一个行政区划文件:

data/county.shp

用 Fiona 读取时,通常是逐条遍历要素:

import fiona

with fiona.open("data/county.shp", "r", encoding="utf-8") as src:
    print(src.crs)
    print(src.schema)

    for feature in src:
        print(feature["properties"])
        print(feature["geometry"]["type"])
        break

用 GeoPandas 读取时,通常是一次性读成一个 GeoDataFrame,也就是带几何列的表格:

import geopandas as gpd

gdf = gpd.read_file("data/county.shp")
print(gdf.crs)
print(gdf.head())
print(gdf.geometry.geom_type.value_counts())

从这个例子可以看出,Fiona读取地理数据时更接近文件本身的要素结构,而 GeoPandas 更接近 pandas 表格分析思路。

背景:为什么 Fiona 和 GeoPandas 经常被放在一起比较

在 Python GIS 生态中,Fiona 和 GeoPandas 的关系非常紧密。很多时候你调用的是 geopandas.read_file(),但背后实际可能会通过 Fiona 或 pyogrio 这类引擎去读取矢量文件。也就是说,GeoPandas 面向用户提供高级接口,而 Fiona 更接近数据源驱动层。

这也是很多初学者困惑的原因:既然 GeoPandas 能读 Shapefile、GeoJSON、GeoPackage,那还需要 Fiona 吗?答案是:看任务类型。

  • 如果你要做属性筛选、空间连接、缓冲区、叠加分析,优先用 GeoPandas。
  • 如果你要逐条读取超大文件、检查 schema、控制字段类型、写入驱动格式,Fiona 更直接。
  • 如果你只是想快速把矢量数据转成表格并分析,GeoPandas 更省事。
  • 如果你需要了解矢量文件的底层结构,Fiona 更适合学习和调试。

原理:Fiona读取地理数据到底读到了什么

Fiona 读取矢量数据时,返回的不是 pandas 表格,而是类似 GeoJSON Feature 的结构。每一条要素通常包含三部分:

  • id:要素编号。
  • properties:属性字段和值。
  • geometry:几何类型和坐标。

例如一条行政区要素可能长这样:

{
    "id": "0",
    "properties": {
        "name": "示例县",
        "code": "330101"
    },
    "geometry": {
        "type": "Polygon",
        "coordinates": [...]
    }
}

而 GeoPandas 读取后得到的是 GeoDataFrame。你可以把它理解成一个普通 pandas DataFrame,只是多了一列特殊的 geometry,这一列存放点、线、面等空间几何对象。

import geopandas as gpd

gdf = gpd.read_file("data/county.shp")

print(type(gdf))
print(gdf.columns)
print(gdf.geometry.name)

因此,Fiona读取地理数据的重点是“读写要素”,GeoPandas 的重点是“分析空间表格”。

步骤:用 Fiona 读取、筛选并保存地理数据

步骤 1:查看数据驱动、坐标系和字段结构

使用 Fiona 时,建议先检查数据的坐标系和 schema。schema 可以理解为矢量图层的字段结构和几何类型定义。

import fiona

input_path = "data/county.shp"

with fiona.open(input_path, "r", encoding="utf-8") as src:
    print("驱动:", src.driver)
    print("坐标系:", src.crs)
    print("字段结构:", src.schema)
    print("要素数量:", len(src))

这一步非常适合排查 Shapefile 字段乱码、几何类型不一致、坐标系缺失等问题。

步骤 2:逐条读取要素

Fiona 的一个优势是可以逐条读取,不一定要把整个文件一次性放进内存。

with fiona.open(input_path, "r", encoding="utf-8") as src:
    for feature in src:
        props = feature["properties"]
        geom = feature["geometry"]

        print(props)
        print(geom["type"])
        break

如果你的文件很大,只需要扫描部分字段,Fiona读取地理数据会比直接加载为 GeoDataFrame 更可控。

步骤 3:按属性筛选要素

下面示例筛选名称字段中包含“区”的要素,并写入新的 GeoPackage 文件。

import fiona

input_path = "data/county.shp"
output_path = "data/county_filtered.gpkg"

with fiona.open(input_path, "r", encoding="utf-8") as src:
    meta = src.meta.copy()

    with fiona.open(
        output_path,
        "w",
        driver="GPKG",
        layer="county_filtered",
        crs=src.crs,
        schema=src.schema,
        encoding="utf-8"
    ) as dst:
        for feature in src:
            name = feature["properties"].get("name", "")
            if "区" in name:
                dst.write(feature)

这个例子体现了 Fiona 的典型用法:保持原始 schema,逐条判断,逐条写出。

步骤:用 GeoPandas 完成同样的任务

步骤 1:读取为 GeoDataFrame

如果你更关心分析和筛选,GeoPandas 的代码会更短。

import geopandas as gpd

gdf = gpd.read_file("data/county.shp")
print(gdf.head())
print(gdf.crs)

步骤 2:按属性筛选

filtered = gdf[gdf["name"].str.contains("区", na=False)]
print(filtered[["name", "geometry"]].head())

步骤 3:保存结果

filtered.to_file(
    "data/county_filtered.gpkg",
    layer="county_filtered",
    driver="GPKG"
)

对于普通 GIS 数据处理任务,GeoPandas 代码更接近“读表、筛选、保存”的思路。尤其是当你熟悉 pandas 时,GeoPandas 会更容易上手。

常见坑:Fiona读取地理数据时容易遇到的问题

1. Shapefile 中文字段或属性乱码

Shapefile 编码历史包袱较多,中文乱码很常见。可以尝试显式指定编码:

with fiona.open("data/county.shp", "r", encoding="utf-8") as src:
    for feature in src:
        print(feature["properties"])
        break

如果 utf-8 不对,可以根据数据来源尝试 gbk。更推荐的做法是把长期使用的数据转换为 GeoPackage,减少 Shapefile 编码和字段长度限制带来的问题。

2. Fiona 读出来的是 dict,不是 DataFrame

这是设计差异,不是错误。Fiona 返回的是一条条 feature。你不能直接使用 gdf["字段名"] 这种 pandas 写法。

如果你需要表格操作,可以把要素整理为列表,或者直接使用 GeoPandas:

import geopandas as gpd

gdf = gpd.read_file("data/county.shp")

3. 写出文件时 schema 不匹配

Fiona 写文件时字段类型必须符合 schema。比如 schema 中某个字段是整数,你却写入字符串,就可能报错或写入失败。

with fiona.open("data/county.shp", "r", encoding="utf-8") as src:
    print(src.schema)

写出前先检查 schema,是 Fiona 工作流中很重要的一步。

4. 坐标系缺失导致后续分析不准

Fiona 和 GeoPandas 都能读取 CRS,也就是坐标参考系统。但如果源数据本身没有正确的坐标系定义,软件并不会自动知道它到底是 WGS84、CGCS2000 还是某个投影坐标系。

如果后续要计算面积、长度或做叠加分析,一定要先确认坐标系。

方法比较:Fiona 与 GeoPandas 到底怎么选

比较项 Fiona GeoPandas
核心定位 矢量数据底层读写接口 空间数据表格分析工具
返回对象 逐条 feature,类似 GeoJSON 结构 GeoDataFrame
适合任务 检查 schema、流式读取、格式转换、精细控制写出 属性筛选、空间分析、空间连接、制图预处理
学习门槛 需要理解 feature、schema、driver 熟悉 pandas 的用户更容易上手
大文件处理 逐条读取更可控 通常会整体加载到内存
空间分析能力 本身不负责复杂空间分析 提供缓冲区、叠加、裁剪、空间连接等能力
典型代码 fiona.open() gpd.read_file()

如果你只是问“Fiona 和 GeoPandas 哪个更好”,这个问题本身不够准确。更实用的判断方式是:

  • 要读取后马上做空间分析:选 GeoPandas。
  • 要检查或控制矢量文件结构:选 Fiona。
  • 要逐条处理很大的矢量数据:优先考虑 Fiona。
  • 要和 pandas 统计分析结合:选 GeoPandas。
  • 要写教学代码理解 GIS 文件结构:Fiona 很有价值。

检查清单:选择 Fiona 还是 GeoPandas 前先确认这些问题

  • 你的目标是“读写文件”还是“空间分析”?读写偏 Fiona,分析偏 GeoPandas。
  • 数据量是否大到不能一次性加载进内存?如果是,优先考虑 Fiona 的逐条读取方式。
  • 是否需要保留原始字段类型和图层 schema?如果需要,Fiona 更直接。
  • 是否需要执行缓冲区、裁剪、叠加、空间连接?如果需要,GeoPandas 更合适。
  • 是否熟悉 pandas?如果熟悉,GeoPandas 的学习成本更低。
  • 是否遇到编码、字段长度、驱动格式问题?可以用 Fiona 先检查数据结构。
  • 是否需要长期保存中间成果?优先考虑 GeoPackage,而不是继续堆 Shapefile。

FAQ:Fiona读取地理数据与 GeoPandas 常见问题

Fiona读取地理数据能不能直接转成 GeoPandas?

可以。最简单的方式通常是直接用 GeoPandas 读取同一个文件。如果你已经用 Fiona 拿到了 feature 列表,也可以再构造成 GeoDataFrame,但多数场景没有必要绕一圈。

import geopandas as gpd

gdf = gpd.read_file("data/county.shp")

GeoPandas 是否完全替代 Fiona?

不能简单说完全替代。GeoPandas 更适合分析,Fiona 更适合底层读写和结构检查。对于 GIS 工程项目,二者经常配合使用:先用 Fiona 排查数据格式问题,再用 GeoPandas 做分析处理。

Fiona 可以做缓冲区分析吗?

Fiona 本身不负责缓冲区分析。缓冲区这类几何运算通常由 Shapely 或 GeoPandas 完成。Fiona 可以负责读入和写出,几何处理交给其他库。

为什么 GeoPandas 读取大文件会慢或占内存?

GeoPandas 通常会把数据加载成 GeoDataFrame,属性和几何对象都进入内存。如果数据量很大,内存压力会明显增加。此时可以考虑 Fiona 逐条处理,或把数据导入 PostGIS 后用数据库完成筛选和空间查询。

Fiona 和 GDAL/OGR 是什么关系?

Fiona 是 Python 中常用的矢量数据读写库,它的能力与 GDAL/OGR 生态密切相关。你可以把 GDAL/OGR 理解为底层地理数据格式支持体系,Fiona 提供了更符合 Python 使用习惯的接口。

新手应该先学 Fiona 还是 GeoPandas?

如果目标是快速完成 GIS 数据分析,建议先学 GeoPandas。如果目标是理解矢量文件结构、字段 schema、驱动格式和数据写出细节,再学习 Fiona。实际工作中,两者都值得掌握。

结论:把 Fiona 当作读写接口,把 GeoPandas 当作分析工具

回到“Fiona读取地理数据?与GeoPandas啥区别?”这个问题,最实用的结论是:Fiona 偏底层,GeoPandas 偏分析。Fiona读取地理数据时,你面对的是 feature、schema、driver 和 CRS;GeoPandas 读取数据后,你面对的是 GeoDataFrame、属性列和 geometry 列。

如果你要写一个稳定的数据转换脚本,尤其需要逐条处理、检查字段结构和控制输出格式,Fiona 很合适。如果你要做筛选、统计、空间连接、缓冲区、叠加分析,GeoPandas 会更高效。真正的 Python GIS 工作流不是二选一,而是根据任务把两者放在合适的位置。