为长格式时间序列数据补全含NA的缺失行(优先dplyr方案)
如何用dplyr优雅地为长格式data.frame补全缺失的观测行?
首先先明确你的原始数据情况:
mydata <- data.frame(year = rep(c(2000,2001,2002,2004), 2), team = factor(c("A","A","A","A", "B","B","B","B")), score = c(8,1,3,1,2,3,7,2)) # 查看原始数据 mydata #> year team score #> 1 2000 A 8 #> 2 2001 A 1 #> 3 2002 A 3 #> 4 2004 A 1 #> 5 2000 B 2 #> 6 2001 B 3 #> 7 2002 B 7 #> 8 2004 B 2
确实,2003年的观测对两个队都缺失了,需要补全这些行并将score填充为NA。
最优dplyr/tidyr方案:用complete()函数
complete()是tidyr包中的函数(属于tidyverse生态,和dplyr无缝配合),专门用来补全数据中缺失的组合,代码非常简洁:
# 先加载tidyverse包(包含dplyr和tidyr) library(tidyverse) # 补全缺失行 mydata_complete <- mydata %>% complete(year = full_seq(year, 1), team)
代码解释:
full_seq(year, 1):自动生成从year列最小值到最大值之间的所有连续整数,这里就是2000-2004的所有年份,解决了年份间隔缺失的问题;team:直接指定这个变量,函数会自动包含它的所有因子水平(A和B),确保每个年份都和每个队组合;- 原来存在的行会保留
score的原始值,缺失的组合会自动将score填充为NA。
如果想要和你目标数据完全一致的排序(先A队的所有年份,再B队的),只需要再加一步arrange():
mydata_complete <- mydata %>% complete(year = full_seq(year, 1), team) %>% arrange(team, year)
最终结果:
mydata_complete #> # A tibble: 10 × 3 #> year team score #> <dbl> <fct> <dbl> #> 1 2000 A 8 #> 2 2001 A 1 #> 3 2002 A 3 #> 4 2003 A NA #> 5 2004 A 1 #> 6 2000 B 2 #> 7 2001 B 3 #> 8 2002 B 7 #> 9 2003 B NA #>10 2004 B 2
补充:expand.grid + left_join方案
你提到的expand.grid也能解决,不过步骤稍多,需要先生成所有可能的组合再做连接:
# 生成所有年份和队的组合 all_combinations <- expand.grid(year = seq(min(mydata$year), max(mydata$year), 1), team = levels(mydata$team)) # 左连接原始数据,补全缺失值 mydata_complete2 <- left_join(all_combinations, mydata, by = c("year", "team")) %>% arrange(team, year)
但显然complete()的方案更符合“优雅简洁”的要求,不需要手动生成组合,一步到位。
内容的提问来源于stack exchange,提问作者chamaoskurumi
相关产品推荐
相关产品推荐

