简介:这份世界红树林空间分布数据以shp矢量格式提供,面向从事生态遥感、海岸带研究、地理信息系统分析及全球变化相关课题的科研人员与高年级学生,可用于红树林范围提取、时空变化监测、制图与空间统计等场景。资源包共17个文件,约285.88MB,核心为shp矢量文件及其配套的shx、dbf、prj、sbn、sbx、cpg等索引与坐标文件,另含xml元数据、pdf说明文档、jpg预览图与txt说明,便于在ArcGIS、QGIS等平台直接加载与二次处理。目前已有79人学习下载。数据源自WCMC011 AtlasMangrove2010 v3.1,附带元数据与许可说明,读者可据此了解数据来源、精度与使用限制,快速完成红树林分布制图、面积统计及与其他空间图层叠加分析,为海岸带生态评估与保护规划提供基础数据支撑。
1. 世界红树林空间分布数据shp:从下载到落库前,先搞清楚它到底是什么
红树林分布数据在海岸带碳汇核算、生态红线划定、蓝碳项目选址里是绕不开的底图。很多人第一次拿到「世界红树林空间分布数据shp」时,以为就是一个面文件,双击打开却发现属性表字段看不懂、坐标系对不上、和本地岸线叠不上。这个标题讲的不是某一篇论文,而是一类数据资产:以 shapefile 为载体的全球红树林范围矢量,常见来源包括全球尺度的遥感解译产品,按年份分幅或整幅发布,字段里通常带面积、分类置信度、国家或区域编码。它解决的是「红树林在哪、边界在哪、面积多少」这三个基础问题,适合做海岸带规划、生态评估、遥感验证的从业者,也适合需要把红树林范围落到 GIS 里做叠加分析的人。shp 只是外壳,真正决定能不能用的是坐标系、字段定义和边界精度。
2. 拿到 shp 之后先别急着打开:坐标系、字段与分幅的核对方法
2.1 为什么全球红树林 shp 经常「看起来对、叠起来错」
全球尺度的红树林矢量,发布方为了控制文件体积,常把坐标系统一为地理坐标系 WGS84(EPSG:4326),单位是度。但很多国内项目底图是投影坐标系,比如 CGCS2000 高斯克吕格或 Web 墨卡托。直接拖进 ArcGIS 或 QGIS,软件会做「动态投影」,屏幕上看着能叠上,一旦做面积计算或缓冲区分析,结果就偏了。血泪经验是:先看.prj文件里写的是什么,再决定要不要投影。如果.prj缺失,shapefile 就丢了坐标系定义,软件会当成未知坐标,这时候不能猜,要去数据说明里找原始 CRS。
核对步骤可以固定成一套:
- 用 QGIS 打开 shp,右键图层属性,看「源」里的 CRS 是不是 EPSG:4326。
- 打开属性表,确认字段名和类型,常见有
area_ha、class、country、year。 - 用「矢量 → 几何工具 → 导出几何信息」检查是否有空几何或自相交。
- 和已知岸线底图叠加,放大到红树林边缘看是否贴合。
如果第 4 步发现整体偏移几百米,大概率是基准面差异,不是数据错,而是需要做基准面转换。
2.2 用 QGIS 做一次最小核对:字段、范围与几何有效性
下面这段 Python 用geopandas读 shp,输出 CRS、字段、范围和几何有效性,适合在落库前跑一遍。代码不依赖 ArcGIS,装好geopandas就能用。
import geopandas as gpd # 读取世界红树林 shp,注意路径不要带中文和空格 gdf = gpd.read_file("./data/mangrove_world.shp") # 1. 看坐标系 print("CRS:", gdf.crs) # 2. 看字段和类型 print("Columns:", gdf.columns.tolist()) print(gdf.dtypes) # 3. 看空间范围,判断是否覆盖目标区域 print("Bounds:", gdf.total_bounds) # 4. 检查几何有效性,无效几何会导致后续叠加失败 invalid = gdf[~gdf.is_valid] print("Invalid geometries:", len(invalid)) # 5. 如果无效,尝试修复 if len(invalid) > 0: gdf["geometry"] = gdf.buffer(0) gdf.to_file("./data/mangrove_world_fixed.shp", encoding="utf-8")逻辑说明:gpd.read_file直接读 shapefile 的全部记录,total_bounds返回[minx, miny, maxx, maxy],用这个和你的研究区范围对比,能快速判断数据是否覆盖目标。is_valid是 Shapely 的几何有效性检查,全球数据里常见自相交多边形,buffer(0)是常用修复手段,但会轻微改变边界,修复后要重新核对面积。参数上,encoding="utf-8"保证中文字段不乱码,如果原数据是GBK,读的时候也要指定。
2.3 分幅数据怎么合并:别用「合并」按钮硬拼
有些全球产品按洲或按国家分幅,比如mangrove_asia.shp、mangrove_africa.shp。合并时如果直接在地图里全选导出,容易丢字段或把坐标系混在一起。稳妥做法是先统一 CRS,再合并,最后重建空间索引。
import geopandas as gpd import pandas as pd from pathlib import Path # 假设分幅文件在同一目录 files = list(Path("./data/tiles").glob("*.shp")) gdfs = [] for f in files: g = gpd.read_file(f) # 统一到 WGS84,避免合并后 CRS 不一致 if g.crs != "EPSG:4326": g = g.to_crs("EPSG:4326") gdfs.append(g) # 合并,ignore_index 避免索引重复 merged = gpd.GeoDataFrame(pd.concat(gdfs, ignore_index=True), crs="EPSG:4326") # 去重:按几何的 WKB 哈希去重,防止分幅重叠 merged["geom_hash"] = merged.geometry.apply(lambda x: x.wkb_hex) merged = merged.drop_duplicates(subset="geom_hash").drop(columns="geom_hash") merged.to_file("./data/mangrove_merged.shp", encoding="utf-8")参数说明:to_crs("EPSG:4326")是投影转换,不是简单改标签,会重算坐标。pd.concat合并属性表,ignore_index=True重置索引。去重那一步很关键,分幅数据在边界处常有重叠多边形,不去重会导致面积重复计算。wkb_hex是几何的二进制表示,相同几何哈希相同,比按属性去重可靠。
3. 把红树林 shp 用起来:面积统计、叠加分析与格式转换
3.1 面积统计:地理坐标系下不能直接算面积
WGS84 下直接调gdf.area得到的是平方度,没有物理意义。正确做法是先投影到等面积投影,比如 Mollweide 或 Albers,再算面积。全球数据常用 Mollweide(EPSG:54009),区域数据可以用当地 Albers。
import geopandas as gpd gdf = gpd.read_file("./data/mangrove_merged.shp") # 投影到 Mollweide 等面积投影 gdf_proj = gdf.to_crs("ESRI:54009") # 计算面积,单位平方米,转公顷 gdf_proj["area_ha"] = gdf_proj.area / 10000 # 按国家汇总,假设有 country 字段 summary = gdf_proj.groupby("country")["area_ha"].sum().reset_index() print(summary.sort_values("area_ha", ascending=False).head(10))逻辑说明:to_crs("ESRI:54009")把地理坐标转成等面积投影,area才是平方米。除以 10000 得公顷。如果字段里本来就有area_ha,要核对它是发布方算的还是你算的,两者可能因投影不同有差异。按国家汇总前,确认country字段没有空值,空值会被groupby丢掉。
3.2 和保护区、岸线叠加:用空间连接而不是手动选
红树林常要和保护区边界、海岸线、行政区划叠加,统计每个保护区内的红树林面积。用sjoin做空间连接,比在桌面软件里一个个选快得多。
import geopandas as gpd mangrove = gpd.read_file("./data/mangrove_merged.shp").to_crs("ESRI:54009") protected = gpd.read_file("./data/protected_areas.shp").to_crs("ESRI:54009") # 空间连接,predicate="intersects" 表示相交即保留 joined = gpd.sjoin(mangrove, protected, how="inner", predicate="intersects") # 按保护区名称汇总红树林面积 result = joined.groupby("protected_name")["area_ha"].sum().reset_index() print(result)参数说明:how="inner"只保留有交集的记录,predicate="intersects"是相交判断,也可以用within表示红树林完全在保护区内。两个图层必须先统一 CRS,否则sjoin会报错或结果错乱。如果红树林多边形跨保护区边界,sjoin会把它拆到多个保护区,面积会重复,需要先做overlay求交再算面积。
3.3 shp 转 GeoJSON、KML 与 3D Tiles 的边界
热搜里常出现arcgis shp转kml、shp转3dtiles、kml转shp。红树林数据转 KML 用于 Google Earth 展示,转 GeoJSON 用于 Web 地图,转 3D Tiles 用于三维场景。转换本身不难,坑在坐标系和字段丢失。
# 用 ogr2ogr 转 GeoJSON,保留 WGS84 ogr2ogr -f GeoJSON mangrove.geojson mangrove_merged.shp -t_srs EPSG:4326 # 转 KML,注意 KML 只支持 WGS84 ogr2ogr -f KML mangrove.kml mangrove_merged.shp -t_srs EPSG:4326 # 转 3D Tiles 通常需要先转成 GeoJSON 或 CityGML,再用工具切片逻辑说明:ogr2ogr是 GDAL 的命令行工具,-f指定输出格式,-t_srs指定目标坐标系。KML 对坐标系要求严格,必须是 WGS84,否则 Google Earth 打不开。转 3D Tiles 不是一步能完成的,常见做法是先转 GeoJSON,再用3d-tiles-tools或 Cesium 的切片工具处理,红树林作为面数据,拉伸成体块才有三维效果。
4. 避坑与排查:红树林 shp 处理中最容易翻车的 5 个点
4.1 现象:面积算出来比论文里大一个数量级
原因:在 WGS84 地理坐标系下直接算面积,得到的是平方度,不是平方米。解决:先投影到等面积投影,再算面积,并核对单位。
4.2 现象:shp 打开后属性表中文乱码
原因:shapefile 的.dbf文件编码不统一,常见是 GBK 或 Latin-1。解决:用geopandas读的时候指定encoding="GBK",或先用 QGIS 另存为 UTF-8。
4.3 现象:和本地岸线叠不上,整体偏移
原因:基准面不同,比如 WGS84 和 CGCS2000 在小比例尺下差异不大,但大比例尺下会偏移。解决:做基准面转换,用pyproj或 ArcGIS 的投影工具,不要只改 CRS 标签。
4.4 现象:合并分幅后面积重复
原因:分幅边界处有重叠多边形。解决:合并后按几何去重,或先做union再算面积。
4.5 现象:转 KML 后 Google Earth 不显示
原因:KML 只支持 WGS84,且对多边形环的方向有要求。解决:转之前统一到 EPSG:4326,用ogr2ogr转,不要手动改后缀。
5. 进阶用法:用红树林 shp 做变化检测与渔网统计
5.1 多期数据做变化检测:先对齐再求差
如果手上有 2000 年和 2020 年两期红树林 shp,可以做变化检测。核心是先把两期数据统一 CRS,再用overlay求差集和交集。
import geopandas as gpd m2000 = gpd.read_file("./data/mangrove_2000.shp").to_crs("ESRI:54009") m2020 = gpd.read_file("./data/mangrove_2020.shp").to_crs("ESRI:54009") # 新增:2020 有而 2000 没有 gain = gpd.overlay(m2020, m2000, how="difference") # 减少:2000 有而 2020 没有 loss = gpd.overlay(m2000, m2020, how="difference") gain["area_ha"] = gain.area / 10000 loss["area_ha"] = loss.area / 10000 print("Gain ha:", gain["area_ha"].sum()) print("Loss ha:", loss["area_ha"].sum())参数说明:overlay的how="difference"返回第一个图层中不与第二个图层重叠的部分。两期数据边界不可能完全一致,求差前可以做一个很小的缓冲区容差,比如buffer(10),避免把边界抖动当成变化。这一步会改变几何,要记录容差值。
5.2 渔网分割统计:把红树林密度落到格网
热搜里渔网分割shp常被提到。做红树林密度分析时,可以生成渔网,统计每个格网内的红树林面积占比。
import geopandas as gpd import numpy as np mangrove = gpd.read_file("./data/mangrove_merged.shp").to_crs("ESRI:54009") bounds = mangrove.total_bounds # 生成 10km 渔网 cell_size = 10000 x = np.arange(bounds[0], bounds[2], cell_size) y = np.arange(bounds[1], bounds[3], cell_size) from shapely.geometry import box cells = [box(xi, yi, xi+cell_size, yi+cell_size) for xi in x for yi in y] grid = gpd.GeoDataFrame(geometry=cells, crs="ESRI:54009") # 求交并统计面积 intersect = gpd.overlay(grid, mangrove, how="intersection") intersect["area_ha"] = intersect.area / 10000 density = intersect.groupby(intersect.index)["area_ha"].sum() # 把密度写回渔网 grid["mangrove_ha"] = density grid["mangrove_ha"] = grid["mangrove_ha"].fillna(0) grid.to_file("./data/mangrove_grid.shp", encoding="utf-8")逻辑说明:box生成方形格网,overlay求交得到每个格网内的红树林碎片,再按格网索引汇总。fillna(0)把没有红树林的格网补零。渔网大小根据研究尺度定,10km 适合区域尺度,1km 适合局地尺度。格网太大会掩盖细节,太小会产生大量空格网,影响后续统计效率。
5.3 一个我常犯的错:忽略 shp 的 2GB 限制
shapefile 单个文件不能超过 2GB,字段名不能超过 10 个字符,字段数也有限。全球红树林数据如果属性多、几何复杂,很容易触顶。我一般会在处理前先转成 GeoPackage 或 PostGIS,做完分析再导出 shp 给需要的人。如果必须用 shp,就按区域切分,别硬塞。希望帮到你。
本文还有配套的精品资源,点击获取