代码之家  ›  专栏  ›  技术社区  ›  Nowak

r将间歇性NA值替换为上一次观察结转(NA.locf)

  •  0
  • Nowak  · 技术社区  · 7 年前

    背景

    我需要根据NA的性质,使用不同的方法替换数据帧中的NA。我的数据框架来自一项重复测量的研究,其中一些NA是受试者辍学的结果,而另一些是间歇性缺失测量的结果,定义为一个或多个缺失测量的序列,然后是一个测量值。 我将间歇性缺失测量称为间歇性NA。

    问题

    我在测试NA是否是间歇性测量缺失的结果,以及我应该使用什么功能来替换这些NA时遇到了问题。理想情况下,我会用na.locf方法替换这些间歇性的na。但我需要用基线或最后观察到的值(以较大值为准)替换掉辍学NA。

    示例

    实施例1

    下面是一个很好的例子,我想用na.locf插补将其作为间歇性na's进行处理:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,NA,NA,15,16,19,NA,12,23,31))
    

    我希望最终结果是:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,34,34,15,16,19,19,12,23,31))
    

    实施例2

    下面是一个很清楚的例子,我想通过以前的非NA观察或基线值(第1次就诊)来输入NA(辍学NA),以最大值为准:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,22,18,15,16,19,NA,NA,NA,NA))
    

    我希望最终结果是:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,22,18,15,16,19,34,34,34,34))
    

    实施例3

    这里有一个需要不同插补的混合NA的复杂示例,其中之前的非NA观察值大于辍学NA的基线观察值(第1次就诊):

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,NA,NA,42,16,19,NA,38,NA,NA))
    

    我需要的结果是:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(34,34,34,42,16,19,19,38,38,38))
    

    实施例4

    另一个复杂的例子是,基线观察(访视1)大于辍学者前一个非NA值:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(40,NA,NA,42,16,19,NA,38,NA,NA))
    

    我需要的结果是:

    data.frame(visit=c(1,2,3,4,5,6,7,8,9,10),value=c(40,40,40,42,16,19,19,38,40,40))
    

    我试过的

    正如@gregor所建议的,当我声明这将解决我的问题时,可以用以下方法测试间歇性NA的存在:

    mutate(is.na(value) & !is.na(lead(value))
    

    但这并不能帮助我输入所有间歇NA,特别是间歇NA的序列(NA1,NA2,NA3,14),其中只有NA3在运行此测试后返回为真。

    1 回复  |  直到 7 年前
        1
  •  0
  •   Nowak    7 年前

    我们可以用 na.locf(..., fromLast = TRUE) 识别尾随 NA 价值和用途 pmax 在他们的底线上。我们将以一个很好的综合格式演示您问题中的示例:

    # consolidate example data
    dd = data.frame(
      example = rep(1:3, each = 10),
      visit = rep(1:10, 3),
      value = c(34,NA,NA,15,16,19,NA,12,23,31,
                34,22,18,15,16,19,NA,NA,NA,NA,
                34,NA,NA,42,16,19,NA,38,NA,NA),
      goal = c(34,34,34,15,16,19,19,12,23,31,
               34,22,18,15,16,19,34,34,34,34,
               34,34,34,42,16,19,19,38,38,38)
    )
    
    library(dplyr)
    dd = dd %>% group_by(example) %>%
      mutate(to_fill = !is.na(zoo::na.locf(value, fromLast = TRUE, na.rm = FALSE)),
             result = if_else(to_fill,
                              zoo::na.locf(value, na.rm = FALSE),
                              pmax(first(value), zoo::na.locf(value, na.rm = FALSE))),
        )
    
    all(dd$goal == dd$result)
    # [1] TRUE
    

    如你所见, result 匹配 goal 完美的列。