You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R中通过多条件分组循环实现气候生态位宽度计算自动化?

自动化计算物种气候生态位宽度

问题背景

现有大型数据集df(简化后展示2个生物气候变量,实际为6个),结构如下:

name   longitude  latitude time_bp       bio01     bio12
1           Species A          24.633301 -27.61670       0  18.5594425  467.2066
2           Species A          25.549999 -28.66670       0  17.1183109  487.5667
3           Species A          29.083300  25.80000       0  21.7980595   28.1200
4           Species B          23.033300 -28.20560       0  17.4872379  398.5200
5           Species B          25.500000  23.00000       0  21.3069401   72.9600
6           Species C          24.633301 -27.61670       0  18.5594425  467.2066
7           Species B          29.600000  -0.13500       0  23.3799686  973.3167
8           Species C          33.750000  16.25000       0  28.5797062  137.5567
9           Species A          33.750000  16.25000       0  28.5797062  137.5567
10          Species C          33.750000  16.25000       0  28.5797062  137.5567
11          Species D          33.750000  16.25000       0  28.5797062  137.5567
12          Species D          33.750000  16.25000       0  28.5797062  137.5567
13          Species A          33.750000  16.25000       0  28.5797062  137.5567
14          Species B          33.750000  16.25000       0  28.5797062  137.5567
15          Species E          33.750000  16.25000       0  28.5797062  137.5567

需完成的任务:

  • 对同一经纬度位置的多时间戳气候数据取平均值
  • 排除不具备至少5个唯一位置数据的物种
  • 计算每个物种的气候生态位宽度(各生物气候变量的最大值与最小值之差)

当前手动处理代码示例:

Splitdf <- split(df, df$name)

SpeciesADat <- Splitdf $`Species A`
SpeciesADat <- split(SpeciesADat, SpeciesADat $latitude)
SpeciesADatBio01List <- c(mean(SpeciesADat$`42.611382`$bio01, na.rm = TRUE),
                          mean(SpeciesADat$`-44.457764`$bio01, na.rm = TRUE),
                          mean(SpeciesADat$`-44.450432`$bio01, na.rm = TRUE),
                          mean(SpeciesADat$`-44.223461`$bio01, na.rm = TRUE),
                          mean(SpeciesADat$`-44.185169`$bio01, na.rm = TRUE))
SpeciesADatBio01List <- na.omit(SpeciesADatBio01List)
SpeciesADatB01Breadth <- max(SpeciesADatBio01List) - min(SpeciesADatBio01List)
SpeciesADatBi012List <- c(mean(SpeciesADat$`42.611382`$bio12, na.rm = TRUE),
                                mean(SpeciesADat$`-44.457764`$bio12, na.rm = TRUE),
                                mean(SpeciesADat$`-44.450432`$bio12, na.rm = TRUE),
                                mean(SpeciesADat$`-44.223461`$bio12, na.rm = TRUE),
                                mean(SpeciesADat$`-44.185169`$bio12, na.rm = TRUE))
SpeciesADatBi012List <- na.omit(SpeciesADatBi012List)
SpeciesADatB012Breadth <- max(SpeciesADatBi012List)-min(SpeciesADatBi012List)
SpeciesAData <- data.frame(Bio01Breadth=c(SpeciesADatB01Breadth),
                           Bio12Breadth=c(SpeciesADatB012Breadth),
                           Species=c("Species A"))

期望最终结果格式:

Bio01Breadth Bio12Breadth            Species
1      32.9588     1912.312          Species A
2      3.878775    248.6758          Species B
3      29.51849    840.4629          Species C                                              

自动化实现方案

方案1:用dplyr高效处理(推荐)

无需手动循环,通过分组操作一站式完成数据清洗与计算:

library(dplyr)

niche_breadth_result <- df %>%
  # 1. 按物种+经纬度分组,计算每个位置的气候变量平均值
  group_by(name, longitude, latitude) %>%
  summarise(across(starts_with("bio"), mean, na.rm = TRUE), .groups = "drop") %>%
  # 2. 按物种分组,筛选出至少有5个唯一位置的物种
  group_by(name) %>%
  filter(n() >= 5) %>%
  # 3. 计算每个bio变量的生态位宽度(max-min)
  summarise(across(starts_with("bio"), ~ max(., na.rm = TRUE) - min(., na.rm = TRUE)),
            .groups = "drop") %>%
  # 4. 重命名列以匹配期望格式
  rename_with(~ paste0("Bio", substr(., 4, 5), "Breadth"), starts_with("bio")) %>%
  # 5. 调整列顺序,将物种列放在最后
  relocate(Species = name, .after = last_col())

代码说明

  • across(starts_with("bio"), ...):自动匹配所有以bio开头的变量,适配实际6个生物气候变量的场景
  • filter(n() >=5):直接排除位置数据不足5个的物种,完成数据清洗
  • 全程无需手动指定物种或位置,自动遍历所有符合条件的物种

方案2:基础R循环实现

如果偏好基础R语法,可通过循环完成:

# 获取所有唯一物种
unique_species <- unique(df$name)
result_list <- list()

for (sp in unique_species) {
  # 提取当前物种数据
  sp_data <- df[df$name == sp, ]
  # 按经纬度分组计算气候变量平均值
  sp_location_means <- aggregate(
    . ~ longitude + latitude,
    data = sp_data[, c("longitude", "latitude", grep("^bio", colnames(sp_data)))],
    FUN = mean, na.rm = TRUE
  )
  
  # 检查是否满足至少5个位置的条件
  if (nrow(sp_location_means) >= 5) {
    # 计算每个bio变量的生态位宽度
    breadth_values <- sapply(
      grep("^bio", colnames(sp_location_means)),
      function(col) max(sp_location_means[[col]], na.rm = TRUE) - min(sp_location_means[[col]], na.rm = TRUE)
    )
    # 整理成数据框并调整列名
    sp_result <- data.frame(t(breadth_values))
    colnames(sp_result) <- paste0("Bio", substr(colnames(sp_result), 4,5), "Breadth")
    sp_result$Species <- sp
    # 添加到结果列表
    result_list[[sp]] <- sp_result
  }
}

# 合并所有结果
niche_breadth_result <- do.call(rbind, result_list)
rownames(niche_breadth_result) <- NULL

结果验证

运行上述任意代码后,niche_breadth_result将输出与期望格式一致的数据框,自动完成数据清洗与生态位宽度计算。

内容的提问来源于stack exchange,提问作者Birdman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:49:51