如何扩展DataFrame补全缺失Family的Presence值(设为0)
问题描述
我有一个包含以下结构的DataFrame:
| Family | Order | Class | Presence | Year | Site | Location | Lat | Long |
|---|---|---|---|---|---|---|---|---|
| Aeshnidae | Odonata | Insecta | 0 | 2021 | KAV01 | NASS | -17.4 | 18.5 |
| Aeshnidae | Odonata | Insecta | 0 | 2023 | KAV01 | NASS | -17.4 | 18.5 |
| Aeshnidae | Odonata | Insecta | 1 | 2021 | KAV02 | NASS | -17.7 | 18.7 |
| Aeshnidae | Odonata | Insecta | 0 | 2023 | KAV02 | NASS | -17.7 | 18.7 |
| Aeshnidae | Odonata | Insecta | 0 | 2021 | KAV03 | NASS | -17.8 | 19.1 |
| Aeshnidae | Odonata | Insecta | 0 | 2023 | KAV03 | NASS | -17.8 | 19.1 |
数据集共有100个唯一的Family,但部分站点(比如KAV03)只覆盖了90个Family的存在/缺失(Presence)值。我需要补全每个站点中缺失的Family条目,将这些条目的Presence设为0,同时保留其余变量的原有值。
我尝试了以下代码但未成功:
MorphoData <- expand.grid( Site = unique(MorphoData$Site), Family = unique(MorphoData$Family), Year = unique(MorphoData$Year) ) %>% left_join(MorphoData, by = c("Site", "Family", "Year")) %>% group_by(Site, Family, Year) %>% mutate( Presence = replace_na(Presence, 0) # Ensure missing Presence values are 0 ) %>% group_by(Site, Year) %>% fill(everything(.), .direction = "downup") %>% # Fill missing taxonomy/spatial data ungroup()
数据示例如下:
data <- data_frame(Site = c("KAV01", "KAV01", "KAV01", "KAV01", "KAV01", "KAV01", "KAV01", "KAV02", "KAV02", "KAV02", "KAV02", "KAV02", "KAV02", "KAV02", "KAV03", "KAV03", "KAV03", "KAV03", "KAV03", "KAV03", "KAV03"), Family = sample(c("Fam1", "Fam2", "Fam3", "Fam4", "Fam5", "Fam6"), 21, replace = TRUE), Year = sample(c(2021, 2022, 2023), 21, replace = TRUE), Presence = sample(c(0, 1), 21, replace = TRUE), Lon = rnorm(n = 21, mean = 5, sd = 1), Lat = rnorm(n = 21, mean = 2, sd = 0.3))
可以看到各站点并未包含所有Family,我希望补全这些缺失的Family并将其Presence设为0。
解决方案
你的代码问题出在填充非缺失变量的分组逻辑,以及expand.grid生成组合时可能遗漏完整Family列表的问题。修正思路如下:
- 先提取每个站点(Site)对应的固定属性(比如Location、Lat、Long),以及每个Family对应的分类属性(Order、Class),避免填充时出错;
- 生成
Site、Family、Year的完整笛卡尔积; - 先关联固定属性,再关联原始数据中的
Presence,最后补全缺失值。
修正后的代码
library(dplyr) library(tidyr) # 提取每个Site对应的固定空间属性(确保每个Site对应唯一值) site_attrs <- MorphoData %>% distinct(Site, Location, Lat, Long) # 提取每个Family对应的分类属性(确保每个Family对应唯一值) family_attrs <- MorphoData %>% distinct(Family, Order, Class) # 生成完整的Site-Family-Year组合 # 注意:如果原始数据中未包含全部100个Family,需手动传入完整的Family列表替换unique(MorphoData$Family) full_combinations <- expand.grid( Site = unique(MorphoData$Site), Family = unique(MorphoData$Family), Year = unique(MorphoData$Year) ) %>% as_tibble() # 补全数据 MorphoData_full <- full_combinations %>% # 关联站点固定属性 left_join(site_attrs, by = "Site") %>% # 关联分类固定属性 left_join(family_attrs, by = "Family") %>% # 关联原始数据中的Presence值 left_join(MorphoData %>% select(Site, Family, Year, Presence), by = c("Site", "Family", "Year")) %>% # 将缺失的Presence设为0 mutate(Presence = replace_na(Presence, 0))
代码说明
- 拆分提取固定属性:每个站点的空间信息、每个Family的分类信息都是固定值,单独提取后再关联,避免用
fill时出现错误填充; - 生成完整组合后,按逻辑依次关联属性和
Presence,最后补全缺失值,逻辑更清晰,避免分组填充带来的冗余问题; - 如果原始数据未包含全部100个Family,需手动传入完整的Family列表(比如
full_family_list <- c("Fam1", "Fam2", ..., "Fam100"))替换unique(MorphoData$Family)。
针对示例数据的测试代码
library(dplyr) library(tidyr) # 提取站点固定属性(示例中每个Site的Lon/Lat是随机生成的,实际应取每个Site的唯一值) site_attrs <- data %>% distinct(Site, .keep_all = TRUE) %>% select(Site, Lon, Lat) # 传入完整的Family列表,而非从示例数据中提取(避免遗漏) full_families <- c("Fam1", "Fam2", "Fam3", "Fam4", "Fam5", "Fam6") # 生成完整组合 full_combinations <- expand.grid( Site = unique(data$Site), Family = full_families, Year = unique(data$Year) ) %>% as_tibble() # 补全数据 data_full <- full_combinations %>% left_join(site_attrs, by = "Site") %>% left_join(data %>% select(Site, Family, Year, Presence), by = c("Site", "Family", "Year")) %>% mutate(Presence = replace_na(Presence, 0))
内容的提问来源于stack exchange,提问作者Daniel Estévez
相关产品推荐
相关产品推荐

