如果前一个值和下一个值一致,则替换缺失值

Replace missing values if previous and next values are consistent

我目前正在处理类似于以下内容的时间序列数据:

ID Var1 Var2 Var3 Var4 Var5
1 A NA A NA A
2 B C NA NA B
3 A A NA NA A
4 A B NA NA B
5 C NA B NA B
df <- data.frame("ID" = c(1, 2, 3, 4, 5),
             "Var1" = c("A", "B", "A", "A", "C"),
             "Var2" = c(NA, "C", "A", "B", NA),
             "Var3" = c("A", NA, NA, NA, "B"),
             "Var4" = c(NA, NA, NA, NA, NA),
             "Var5" = c("A", "B", "A", "B", "B"))

如果第一个非缺失的前一个值和第一个非缺失的下一个值一致,我希望填写“NA”值。也就是说,期望的结果是

ID Var1 Var2 Var3 Var4 Var5
1 A A A A A
2 B C NA NA B
3 A A A A A
4 A B B B B
5 C NA B B B

ID = 2 的数据没有被替换,因为 Var2 和 Var5 不匹配。此外,由于 Var1 和 Var3 不一致,因此不会替换 Var2 处 ID = 2 的缺失值。我正在为如何实现这一点而苦苦挣扎,我们将不胜感激。

  1. 转向更长的时间以利用 tidyr::fill()
  2. 使用 fill() 创建 fill_downfill_up 列,其中将分别包含上一个和下一个 non-missing 值。
  3. 如果前一个 non-missing == 下一个 non-missing,则使用该值;否则保持价值不变。 (这也将保持 non-missing 值不变,因为在这种情况下,前一个 non-missing 将始终 == 下一个 non-missing。)
  4. 转回原始格式。
library(tidyverse)

df_filled <- df %>% 
  pivot_longer(!ID) %>% 
  mutate(
    fill_down = value,
    fill_up = value
  ) %>% 
  group_by(ID) %>% 
  fill(fill_down) %>% 
  fill(fill_up, .direction = "up") %>% 
  mutate(value = if_else(fill_down == fill_up, fill_down, value)) %>% 
  ungroup() %>% 
  pivot_wider(id_cols = ID)
  
df_filled
# # A tibble: 5 x 6
#      ID Var1  Var2  Var3  Var4  Var5 
#   <dbl> <chr> <chr> <chr> <chr> <chr>
# 1     1 A     A     A     A     A    
# 2     2 B     C     NA    NA    B    
# 3     3 A     A     A     A     A    
# 4     4 A     B     B     B     B    
# 5     5 C     NA    B     B     B