在R中计算分组职业暴露时长(去重重叠年份)遇报错求解决
职业暴露数据库分组暴露时长计算报错解决方法
问题背景
现有大型职业暴露数据库,需计算每个研究对象对试剂分组的总暴露时长,要求不同职业接触同一分组试剂时,重叠年份仅统计一次。原计算单试剂暴露时长的代码可正常运行,但将试剂分为M组(A、B)和N组(C、D)后,运行类似代码时出现报错。
报错信息
Error in `summarise()`: ! Problem while computing `year = seq(YEARIN, YEAROUT, by = 1)`. ℹ The error occurred in group 5: ID = 7, JOB = 1, AGENT_GROUP = "M". Caused by error in `seq.default()`: ! 'from' must be of length 1 Run `rlang::last_error()` to see where the error occurred.
数据结构
初始数据
structure(list(ID = c(2, 2, 2, 2, 7, 7, 15, 18, 18, 18, 18, 18, 20, 20, 20), JOB = c(1, 2, 7, 8, 1, 1, 1, 1, 2, 4, 2, 3, 3, 4, 6), AGENT = c("A", "A", "B", "B", "B", "A", "A", "D", "D", "D", "A", "A", "C", "C", "C"), YEARIN = c(1998, 1996, 1979, 1978, 1973, 1973, 1979, 1976, 1980, 1970, 1978, 1984, 1988, 1996, 2000 ), YEAROUT = c(2009, 2000, 1985, 1982, 2006, 2006, 2007, 1985, 2008, 2005, 1979, 1995, 1993, 2002, 2008)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L))
分组后数据
structure(list(ID = c(2, 2, 2, 2, 7, 7, 15, 18, 18, 18, 18, 18, 20, 20, 20), JOB = c(1, 2, 7, 8, 1, 1, 1, 1, 2, 4, 2, 3, 3, 4, 6), AGENT = c("A", "A", "B", "B", "B", "A", "A", "D", "D", "D", "A", "A", "C", "C", "C"), YEARIN = c(1998, 1996, 1979, 1978, 1973, 1973, 1979, 1976, 1980, 1970, 1978, 1984, 1988, 1996, 2000 ), YEAROUT = c(2009, 2000, 1985, 1982, 2006, 2006, 2007, 1985, 2008, 2005, 1979, 1995, 1993, 2002, 2008), AGENT_GROUP = c("M", "M", "M", "M", "M", "M", "M", "N", "N", "N", "M", "M", "N", "N", "N")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -15L))
原正常运行代码(单试剂计算)
datatest %>% group_by(ID, JOB, AGENT) %>% summarise(year = seq(YEARIN, YEAROUT, by=1)) %>% unnest(year) %>% group_by(ID, AGENT) %>% summarise(nyear = length(unique(year)))
问题原因
同一ID、JOB、AGENT_GROUP下存在重复行(如ID=7、JOB=1、AGENT_GROUP=M的两行,YEARIN和YEAROUT完全相同),导致seq()函数接收到长度大于1的from和to参数,触发报错(seq()要求输入为单个值)。
解决方案
方案1:先去重再计算
针对同一分组内时间区间完全重复的情况,先删除重复行,再执行原逻辑:
# 第一步:创建试剂分组字段 datatest <- datatest %>% mutate(AGENT_GROUP = case_when( AGENT %in% c("A", "B") ~ "M", AGENT %in% c("C", "D") ~ "N", TRUE ~ NA_character_ )) # 第二步:去重后计算分组暴露时长 datatest %>% distinct(ID, JOB, AGENT_GROUP, YEARIN, YEAROUT, .keep_all = TRUE) %>% group_by(ID, JOB, AGENT_GROUP) %>% summarise(year = seq(YEARIN, YEAROUT, by = 1), .groups = "drop_last") %>% unnest(year) %>% group_by(ID, AGENT_GROUP) %>% summarise(nyear = length(unique(year)), .groups = "drop")
方案2:直接合并所有时间区间(更通用)
不管组内是否有重复,直接生成所有年份序列后合并去重,适用于同一分组内存在不同时间区间的场景:
# 创建试剂分组字段 datatest <- datatest %>% mutate(AGENT_GROUP = case_when( AGENT %in% c("A", "B") ~ "M", AGENT %in% c("C", "D") ~ "N", TRUE ~ NA_character_ )) # 计算分组暴露时长 datatest %>% group_by(ID, AGENT_GROUP) %>% summarise( year = purrr::map2(YEARIN, YEAROUT, ~seq(.x, .y, by = 1)) %>% unlist(), .groups = "drop" ) %>% mutate(year = unique(year)) %>% group_by(ID, AGENT_GROUP) %>% summarise(nyear = n(), .groups = "drop")
内容的提问来源于stack exchange,提问作者R_help
相关产品推荐
相关产品推荐

