如何在R语言中为数据框按姓名-年份维度补全缺失周数据并填充Total值为0
如何按Name+Year组合补全年份内缺失的Week行并填充Total为0?
问题背景
你有如下的原始数据:
| Name | Year | Week | Total |
|---|---|---|---|
| John | 2021 | 1 | 3 |
| John | 2021 | 2 | 2 |
| John | 2021 | 5 | 1 |
| John | 2021 | 10 | 2 |
| Mary | 2020 | 3 | 1 |
| Mary | 2021 | 5 | 2 |
需求是针对每个Name+Year的组合,补全年份内所有缺失的Week行,同时把对应Total设为0(比如John 2021需要补全Week3-4、6-53的行,Total都是0)。
你当前尝试的代码是:
data1<-data %>% complete(Week = seq(min(Week), max(Week), by = 'week')) %>% mutate_each(funs(ifelse(is.na(.),0,.)))
但这段代码没有实现预期效果,问题出在没有按分组补全,且只覆盖了现有数据的Week区间,而非整个年份的所有周数。
正确解决方案
我们可以用tidyverse工具链里的group_by()+complete()+replace_na()来实现需求,步骤如下:
完整可运行代码
library(tidyverse) # 先构造你的示例数据(如果已有数据可以跳过这步) data <- tibble( Name = c("John", "John", "John", "John", "Mary", "Mary"), Year = c(2021, 2021, 2021, 2021, 2020, 2021), Week = c(1, 2, 5, 10, 3, 5), Total = c(3, 2, 1, 2, 1, 2) ) # 核心处理逻辑 data_complete <- data %>% # 关键:按Name和Year分组,确保每个用户的每个年份单独补全 group_by(Name, Year) %>% # 补全该年份的所有Week(ISO标准一年最多53周) complete(Week = 1:53) %>% # 将缺失的Total值替换为0 replace_na(list(Total = 0)) %>% # 取消分组,恢复常规数据框状态 ungroup() # 查看John 2021的补全结果 data_complete %>% filter(Name == "John", Year == 2021)
代码细节说明
- 分组是核心:
group_by(Name, Year)保证我们不会把Mary的2020和John的2021的Week混在一起处理,每个组合独立补全年份内的周数。 - 精准补全周数:用
Week = 1:53直接覆盖ISO周历的所有可能周数(大部分年份是52周,少数年份有53周)。如果你想更精准地匹配每个年份的实际周数,可以用lubridate包计算该年份最后一天的周数:library(lubridate) data_complete <- data %>% group_by(Name, Year) %>% # 计算该年份最后一天的ISO周数,作为补全的上限 complete(Week = 1:isoweek(as.Date(paste(Year, 12, 31, sep = "-")))) %>% replace_na(list(Total = 0)) %>% ungroup() - 优雅填充缺失值:
replace_na(list(Total = 0))是tidyverse推荐的写法,比旧的mutate_each更精准,只针对Total列的缺失值替换,避免影响其他列。
内容的提问来源于stack exchange,提问作者akang
相关产品推荐
相关产品推荐

