【问题标题】:NA filling only if "sandwiched" by the same value using dplyr仅当使用 dplyr 被相同的值“夹在中间”时才填充 NA
【发布时间】:2019-01-13 04:57:41
【问题描述】:

好的,这是另一个缺失值填充问题。

我正在寻找一种方法来根据列中的前一个和下一个现有值填充 NA。单一方向的标准填充不足以完成此任务。

如果列中的前一个和下一个有效值不相同,则该块保持为 NA。

示例数据框的代码为:

df_in <- tibble(id= 1:12,
        var1 = letters[1:12],
        var2 = c(NA,rep("A",2),rep(NA,2),rep("A",2),rep(NA,2),rep("B",2),NA))

谢谢,

【问题讨论】:

  • “如果列中的上一个和下一个有效值不同,则该块保持为 NA。” 根据您的规则,我不知道如何第 4 行和第 5 行被填满。在第 4 行中,前一个值为 A,下一个值为 NA。因此它应该保持NA。第 5 行也是如此。您能澄清一下吗?
  • @MauritsEvers 我认为“有效”在这里应该解释为“不是NA”。
  • @Florian 嗯,是的,我认为你是对的:-)

标签: r dplyr na


【解决方案1】:

比较na.locf()(最后一个观察结果向前)和na.locf(fromLast = TRUE)(向后):

mutate(df_in, 
       var_new = if_else(
         zoo::na.locf(var2, na.rm = FALSE) == 
           zoo::na.locf(var2, na.rm = FALSE, fromLast = TRUE),
         zoo::na.locf(var2, na.rm = FALSE),
         NA_character_
       ))

# # A tibble: 12 x 4
#       id var1  var2  var_new
#    <int> <chr> <chr> <chr>  
#  1     1 a     NA    NA     
#  2     2 b     A     A      
#  3     3 c     A     A      
#  4     4 d     NA    A      
#  5     5 e     NA    A      
#  6     6 f     A     A      
#  7     7 g     A     A      
#  8     8 h     NA    NA     
#  9     9 i     NA    NA     
# 10    10 j     B     B      
# 11    11 k     B     B      
# 12    12 l     NA    NA 

【讨论】:

  • 快速跟进问题(稍微不相关):我注意到如果将 mutate 应用于原始变量“var2”,则在 if_else 语句的末尾使用一个简单的 NA 就足够了.为什么在变异为新变量时,if_else 语句末尾需要NA_character_ 而不是普通的NA
  • 对我来说,分配给var2var_new 并不重要,我只使用NA 就会出错,因为dplyr::if_else()(带有_)确实会输入检查。但请注意,我已经编辑了我的答案并且最初使用了base::ifelse(没有_),它不检查类型并且之后会强制执行
【解决方案2】:

这样的?

df_in %>% mutate(var_new = {
       tmp <- var2
       tmp[is.na(tmp)] <- "NA"
       rl <- rle(tmp)
       tibble(before = c(NA, head(rl$values, -1)),
              value  = rl$values,
              after  = c(tail(rl$values, -1), NA),
              lengths = rl$lengths) %>%
       mutate(value = ifelse(value == "NA" & before == after, before, value),
              value = ifelse(value == "NA", NA, value)) %>%
       select(value, lengths) %>%
       unname() %>%
       do.call(rep, .)})

# # A tibble: 12 x 4
#       id var1  var2  var_new
#    <int> <chr> <chr> <chr>  
#  1     1 a     NA    <NA>   
#  2     2 b     A     A      
#  3     3 c     A     A      
#  4     4 d     NA    A      
#  5     5 e     NA    A      
#  6     6 f     A     A      
#  7     7 g     A     A      
#  8     8 h     NA    <NA>   
#  9     9 i     NA    <NA>   
# 10    10 j     B     B      
# 11    11 k     B     B      
# 12    12 l     NA    <NA>

说明

  1. NA 转换为"NA"(因为rle 不算连续的NA。)
  2. 创建tmp 的运行长度编码表示
  3. 现在您可以查看相关块之前和之后的值
  4. 替换值。

【讨论】:

  • var_new 的值与 var2 的值相同。似乎什么都没有填满。你能再检查一下吗?
  • 抱歉忘记了我的代码中的一行,现已更新。基本上,您需要将NA 转换为"NA",因为rle 不计算连续的NA,而是将它们视为不同的值
  • 不错的@thothal +1
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
  • 2021-04-21
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2022-01-13
相关资源
最近更新 更多