如何让tidyr::complete的fill参数按seg分组匹配对应年份值?
问题与解决方案
问题描述
我有一个包含不同年龄组个体比例信息的数据集,正在使用tidyr的complete函数,为某年份未记录的年龄组补充对应的比例NA值。此外,数据中的连续年份由seg值标识(例如1988-1993对应seg=1,1998-2003对应seg=2),我不希望补全年份缺失值。
当前使用的代码如下:
df <- structure(list(site = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), levels = "A", class = "factor"), year = c(1988, 1988, 1989, 1989, 1989, 1990, 1990, 1991, 1991, 1991, 1992, 1992, 1992, 1993, 1993, 1993, 1998, 1998, 1998, 1999, 1999, 1999, 2000, 2000, 2000, 2001, 2001, 2001, 2002, 2002, 2003, 2003, 2003), age = c(`9104` = 1, `9341` = 2, `9292` = 1, `9632` = 2, `9960` = 4, `9543` = 1, `9857` = 3, `9685` = 1, `9968` = 2, `10169` = 3, `9858` = 1, `10127` = 2, `10212` = 3, `10009` = 1, `10284` = 2, `10522` = 6, `10464` = 1, `10605` = 2, `10830` = 3, `10556` = 1, `10744` = 2, `11056` = 3, `10687` = 1, `11061` = 2, `11279` = 5, `10912` = 1, `11109` = 2, `11197` = 3, `11065` = 1, `11194` = 2, `11154` = 1, `11255` = 2, `11324` = 3), pAGE = c(0.972, 0.028, 0.964, 0.005, 0.031, 0.823, 0.177, 0.921, 0.074, 0.004, 0.846, 0.045, 0.109, 0.833, 0.155, 0.012, 0.927, 0.054, 0.019, 0.784, 0.21, 0.005, 0.958, 0.017, 0.025, 0.852, 0.124, 0.024, 0.913, 0.087, 0.909, 0.073, 0.019), seg = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)), row.names = c(NA, -33L), class = c("tbl_df", "tbl", "data.frame")) library(tidyr) df %>% complete(year, nesting(site), age, fill = list(seg = 999))
请问能否修改fill = list(seg = 999),使得补充的seg值与对应年份已有seg值一致(即seg=1的年份补充seg=1,seg=2的年份补充seg=2),而非设置固定值?类似fill = list(seg = lag(seg))的效果。
解决方案
可以通过分组后补全的方式实现,因为每个year和site对应的seg是唯一固定的,我们先按year、site、seg分组,再对age进行补全,这样新增的行会自动继承分组内的seg值,无需手动指定固定填充值:
library(tidyr) library(dplyr) df %>% group_by(year, site, seg) %>% complete(age) %>% ungroup()
原理说明
- 分组操作
group_by(year, site, seg)确保每个分组内的seg值是统一的(比如1988年的分组seg都是1) complete(age)仅在当前分组内补全缺失的age类别,新增行的year、site、seg都会沿用分组的对应值- 最后用
ungroup()取消分组,恢复数据框的常规结构
如果需要先明确所有可能的age类别(比如跨年份的所有age值),可以先提取全局的age集合,再传入complete:
all_ages <- df %>% pull(age) %>% unique() df %>% group_by(year, site, seg) %>% complete(age = all_ages) %>% ungroup()
这样能确保每个年份都包含所有出现过的age类别,缺失的pAGE会自动设为NA,而seg则和对应年份保持一致。
内容的提问来源于stack exchange,提问作者tnt
相关产品推荐
相关产品推荐

