使用dplyr::complete()按站点运营起止年展开数据集报错求助
将站点运营年份范围展开为逐年记录
编辑:尽管此问题已关闭,但需注意,现有答案采用的dplyr方法与2012年原问题的解法差异较大,这些新答案可能对其他用户有帮助。
我有一份包含各站点运营起止年份(minY、maxY)的数据集,希望将其展开为每个运营年份对应一行的形式。
示例数据集
set.seed(42) df <- data.frame( site = rep(LETTERS[1:10]), minY = sample(1980:1990, 10), maxY = sample(2000:2010, 10) ) df site minY maxY 1 A 1980 2007 2 B 1984 2006 3 C 1990 2003 4 D 1988 2000 5 E 1981 2004 6 F 1983 2005 7 G 1986 2008 8 H 1989 2001 9 I 1987 2009 10 J 1985 2010
最终数据集中,A站点应有28行(对应每个运营年份)。
尝试的方法及报错
我尝试使用complete()函数实现,但持续报错:
complete(df, nesting(site), fill = list(value1 = minY, value2 = maxY)) Error in vec_is_list(replace) : object 'minY' not found
解决方案
方法1:tidyverse简洁实现(推荐)
利用dplyr分组后结合tidyr::complete生成年份序列,这是最直观的tidyverse方法:
library(dplyr) library(tidyr) df_expanded <- df %>% group_by(site) %>% complete(year = minY:maxY) %>% ungroup() # 验证A站点行数 nrow(filter(df_expanded, site == "A")) # 输出28,符合要求
方法2:逐行生成序列再展开
如果需要保留原有的minY和maxY列,也可以先按行生成年份列表,再展开:
df_expanded <- df %>% rowwise() %>% mutate(year = list(minY:maxY)) %>% unnest(year) %>% ungroup()
方法3:基础R实现
无需额外包的情况下,用lapply遍历每行生成对应数据框,再合并:
df_expanded <- do.call(rbind, lapply(1:nrow(df), function(i) { data.frame( site = df$site[i], year = seq(df$minY[i], df$maxY[i]), minY = df$minY[i], maxY = df$maxY[i] ) }))
关于complete()报错的原因
你之前的complete()用法错误,该函数的核心是补全已存在的分组组合,而非生成连续序列。正确的用法需要在分组后,指定year的序列范围为当前组的minY到maxY,如方法1所示。
内容的提问来源于stack exchange,提问作者tnt
相关产品推荐
相关产品推荐

