参考文献
本文对一篇 2022 年发表在 New Phytologist 的绘图方法文章中的技术路线进行复现。
An integrated high-resolution mapping shows congruent biodiversity patterns of Fagales and Pinales
Summary
文中,作者针对在全球尺度上绘制物种分布图提出了一种全新的方法。该方法整合了 多边形绘图(polygon mapping)和 物种分布模型(species distribution modelling,SDM)。
在 多边形绘图算法 中,考虑了:
- 分布距离(distances of occurrences)
- 分布嵌套(nestedness of occurrences)
在 物种分布模型 中,考虑了 :
- 多重建模算法(multiple modelling algorithm)
- 复杂度(complexity levels)
- 伪非分布区选择(pseudo-absence selections)
Materials and Methods
该新方法的整体流程有 5 个步骤:
- 数据收集(data collection)
- 数据清洗(data cleaning)
- 参数优化(parameter optimization)
- 集成绘图(mapping by integration of SDM and polygons)
- 地图检验(map validating)
下面进入正题。
新方法的步骤流程及细节
1. 数据收集与整合(Data collection and merging)
文中,作者通过手动或R包从48个数据库中获取数据。为了减小因为某些类群的观测数据很少而低估了该类群的分布范围的风险,作者不仅收集了使用文字记录的数据库,还从已存在的分布图上获取分布记录,包括raster、shape甚至是专家手绘的地图。最后,所有的分布数据都转换为使用十进制 经/纬度格式 的 EPSG 4326。有关EPSG 4326的内容请自己查阅。
那么,实际的情况到底是怎样的呢?我们一起来看脚本 1_get_species_occurences.R。
该脚本是作者通过 rgbif 和 BIEN 来收集数据,其中下面两行表示搜集的数据只包含3列内容:物种名(Taxon),经度(x)和 维度(y)。
colnames(GBIFgetAll) <- c("Taxon", "x", "y")colnames(BIENgetAll) <- c("Taxon", "x", "y")
同时,从给出的示例数据集 allGBIFandBIEN_Occurrences.rds 也能看出来:
Taxon | x | y | |
1 | Pinus halepensis Mill. | 0.069 | 38.645 |
2. 数据清洗(Data cleaning)
文中介绍的数据清洗可以分为四个步骤:
- 首先是针对名称进行的处理,
- 然后是针对坐标进行的处理,
- 接着是根据物种原生区进行处理,
- 最后是根据模型运算要求进行处理。
2.1. 针对数据中名称部分的清洗
根据 Catalogue of Life 对数据中 物种的同源异名(synonymous)、未处理名称(unresolved)、错误拼写(misspelled)或错误名称(wrong)和 错误或缺失的科名 进行标准化、更正或增加。
之后如下处理:
- 只保留具有标准物种名称的记录
- 去除所有重复记录
- 将亚种记录视为种级记录
- 去除所有杂交种记录
2.2. 针对数据中坐标部分的清洗
为了剔除人工栽培的分布记录和坐标点错误的记录,文中作如下处理:
- 去除:以国家首都为中心,半径 10km 内的记录。
- 去除:以国家中心为中心,半径 5km 内的记录。
- 去除:以多样性研究机构为中心,半径 1km 内的记录。
- 去除:以GBIF总部为中心,半径 0.5° 内的记录。
- 去除:以 坐标点 0,0为中心,半径 0.5° 内的记录。
2.3. 根据物种原生区对数据进行清洗
从 POWO 上获取所有物种的区级原生分布区,在原生分布区的基础上向外延伸 2°,如果记录未在范围内则去除。
如果此时某物种的记录有超过 50% 已经被去除,那么就要人工进行检查,确保没有丢弃好数据。
2.4. 根据模型运算要求对数据进行清洗
物种分布记录的不均匀性可能会增加模型运算的不准确性,还可能会增加因为零散分布的记录导致 SDM 出现权重偏差,进而导致低估了物种的分布范围。
因此,针对物种记录数量 >50,去除间距小于 0.1° 的记录。
2.#. 数据清洗的流程重现
作者提供了 2.1_occurrences_nameCorrection_primaryCleaning.R 和 2.2_(optional)_occurrences_deepCleaning.R 两个脚本进行数据清洗。下面笔者将逐行进行分析:
2.#.1. occurrences_nameCorrection_primaryCleaning.R
首先,它要求设置 工作路径(wkpath),随即生成数据清洗后的保存路径:
wkpath <- "D:/Work_Space/My-scripts/R/gdplants-main"
setwd(wkpath)name.correct.folder <- "./2.1_name_correction/"
cc.cleaned <- "./2.2_cleaning_cc/cleaning_cc_occurrences/"
cc.cleaned.report <- "./2.2_cleaning_cc/cleaning_cc_report/"
cc.cleaned.detail <- "./2.2_cleaning_cc/cleaning_cc_detail/"
示例使用的数据应该有以下三列:"sciName", "x", "y",分别表示原始的物种名,经度和纬度。
occ.all <- readRDS("./example/allGBIFandBIEN_Occurrences.rds")
此时,在 R 的工作环境里应该包含下图中的变量:
数据清洗中需要用到第三方的软件包,脚本中也给出了相应的代码:
options(repos=structure(c(CRAN="https://stat.ethz.ch/CRAN/")))packages <- c("Taxonstand", "CoordinateCleaner", "rgdal", "sp")for (p in packages) {if(!library(package = p, logical.return = TRUE, character.only = TRUE)){install.packages(p)library(package = p, character.only = TRUE)} else { library(package = p, character.only = TRUE) }
}
注意:Taxonstand 和 rgdal 已经在CRAN下架了,官方建议使用 WorldFlora 和 sf/terra 替换。但是仍可在网页上搜索资源进行安装。
加载好软件包后,继续创建输出的保存路径文件夹:
if(!dir.exists(name.correct.folder)) {dir.create(name.correct.folder, recursive = T)}
if(!dir.exists(cc.cleaned)) {dir.create(cc.cleaned, recursive = T)}
if(!dir.exists(cc.cleaned.report)) {dir.create(cc.cleaned.report, recursive = T)}
if(!dir.exists(cc.cleaned.detail)) {dir.create(cc.cleaned.detail, recursive = T)}
这里已经为两个脚本都准备好了文件下,下面就正式进行清洗工作了,让我们一起来梳理脚本的处理思路。
2.#.1.1. 针对数据中名称部分的清洗
spname0 <- as.character(unique(na.omit(occ.all[ ,"Taxon"]$Taxon)))name.correct0 <- TPL(spname0)
首先将采集数据中的 物种名 提取并去重,然后使用 Taxonstand::TPL() 进行物种名匹配。
因为 The Plant List 已经停止提供服务了,所以建议使用 WorldFlora。因为下载速度太慢,笔者使用了 U.Taxonstand。
library(U.Taxonstand)
library(openxlsx)
dat1 <- read.xlsx("D:/ALL_Softwares/R-4.2.0/library/U.Taxonstand/Database-main/Plants_WFO_database_20220701/Plants_WFO_database_part1.xlsx")
dat2 <- read.xlsx("D:/ALL_Softwares/R-4.2.0/library/U.Taxonstand/Database-main/Plants_WFO_database_20220701/Plants_WFO_database_part2.xlsx")
dat3 <- read.xlsx("D:/ALL_Softwares/R-4.2.0/library/U.Taxonstand/Database-main/Plants_WFO_database_20220701/Plants_WFO_database_part3.xlsx")
WFO_database <- rbind(dat1, dat2, dat3)
rm(dat1, dat2, dat3)spname0 <- as.character(unique(na.omit(occ.all[ ,"Taxon"]$Taxon)))
# name.correct0 <- TPL(spname0)name.correct0 <- nameMatch(spList = spname0, spSource = WFO_database)
name.correct0['Taxon'] <- paste(name.correct0$Submitted_Name, name.correct0$Submitted_Author)name.correct <- merge(occ.all, name.correct0)
这样,原始数据中就增加了匹配后的名称信息。具体的数据结构请参考R语言实践——U.Taxonstand标准化动植物科学名。
接着挑选出所有匹配到接受名的记录:
name.corrected <- name.correct[which(is.na(name.correct$New_name) | !grepl("Accepted name needs to be determined", name.correct$New_name