【问题标题】:R Impute NA's by Linear Increase Depending on Time IntervalR 根据时间间隔通过线性增加来估算 NA
【发布时间】:2018-07-24 19:34:49
【问题描述】:

问题

我需要在来自重复测量研究的数据框中估算 NA。对于这个特定的结果,我需要从最后一个观察值开始,按每 +52 周的时间间隔用最后观察到的非 NA 值 +1 估算 NA。 p>

示例

包含目标插补目标的示例数据框。

df <- data.frame(
  subject = rep(1:3, each = 12),
  week = rep(c(8, 10, 12, 16, 20, 26, 32, 44, 52, 64, 78, 104),3),
  value = c(112, 97, 130, 104, NA, NA, NA, NA, NA, NA, NA, NA,
            89, 86, 94, 96, 88,107, 110, 102, 107, NA, NA, NA,
            107, 110, 102, 130, 104, 88, 82, 79, 92, 106, NA, NA),
  goal = c(112, 97, 130, 104, 104, 104, 104, 104, 104, 104, 105, 105,
            89, 86, 94, 96, 88,107, 110, 102, 107, 107,107, 108,
            107, 110, 102, 130, 104, 88, 82, 79, 92, 106, 106, 106)
)

【问题讨论】:

  • 行号 11&12 的 goal 为 105 的逻辑是什么?
  • 因为在第 11 行和第 12 行中,week 的值距离上次观察值超过 52 周。
  • 由于第 4 行是受试者 1 = 104 的最后观察到的非 NA 值,这是在第 16 周测量的,+1 插补需要从第 16+52=68 周开始进行。第 11&12 行是第 78&104 周,这意味着这些 NA 需要按 104+1=105 估算。

标签: r dplyr zoo


【解决方案1】:

我保留了中间列以使正在发生的事情更加明显,但您可以使用简单的select 删除它们。

df = df %>%
  group_by(subject) %>%
  mutate(last_obs_week = max(week[!is.na(value)]),
         since_last_week = pmax(0, week - last_obs_week),
         inc_52 = since_last_week %/% 52,
         result = zoo::na.locf(value) + inc_52
  ) 

all(df$goal == df$result)
# [1] TRUE

print.data.frame(df)
#    subject week value goal last_obs_week since_last_week inc_52 result
# 1        1    8   112  112            16               0      0    112
# 2        1   10    97   97            16               0      0     97
# 3        1   12   130  130            16               0      0    130
# 4        1   16   104  104            16               0      0    104
# 5        1   20    NA  104            16               4      0    104
# 6        1   26    NA  104            16              10      0    104
# 7        1   32    NA  104            16              16      0    104
# 8        1   44    NA  104            16              28      0    104
# 9        1   52    NA  104            16              36      0    104
# 10       1   64    NA  104            16              48      0    104
# 11       1   78    NA  105            16              62      1    105
# 12       1  104    NA  105            16              88      1    105
# 13       2    8    89   89            52               0      0     89
# ...

【讨论】:

    【解决方案2】:

    可以使用dplyrtidyr::fill 来获得所需的结果。逻辑将是添加一个列来跟踪具有non-NA 值的week。使用tidyr::fill 填充最后一个non-NA 值,然后检查当前周与上一个non-NA 周的差异是否大于52,然后将该值增加1

    library(dplyr)
    library(tidyr)
    
    df %>% group_by(subject) %>%
      mutate(weekWithLastNonNaValue = ifelse(is.na(value), NA, week)) %>%
      fill(value, weekWithLastNonNaValue) %>%
      mutate(value = value + (week-weekWithLastNonNaValue) %/% 52) %>%
      select(-weekWithLastNonNaValue) %>%
      as.data.frame()
    
    # subject week value goal
    # 1        1    8   112  112
    # 2        1   10    97   97
    # 3        1   12   130  130
    # 4        1   16   104  104
    # 5        1   20   104  104
    # 6        1   26   104  104
    # 7        1   32   104  104
    # 8        1   44   104  104
    # 9        1   52   104  104
    # 10       1   64   104  104
    # 11       1   78   105  105
    # 12       1  104   105  105
    # 13       2    8    89   89
    # 14       2   10    86   86
    # 15       2   12    94   94
    # 16       2   16    96   96
    # 17       2   20    88   88
    # 18       2   26   107  107
    # 19       2   32   110  110
    # 20       2   44   102  102
    #
    # so on
    #
    

    【讨论】:

    • 我建议在我的回答中使用%/% 作为增量值,因此它可以推广到具有较大偏移量的情况 - OP 说它需要为每 +52 周的差异 +1,我think 表示 +2 表示 104,+3 表示 156 等。(部分基于 OP 的 cmets on this other question that led to this one
    • 谢谢@Gregor。是的,如果 OP 打算为每 52 增加 +1,则需要 %/%。我会更新我的答案。
    猜你喜欢
    • 1970-01-01
    • 2019-07-24
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    • 1970-01-01
    • 2018-07-08
    • 2019-01-13
    • 2016-08-01
    相关资源
    最近更新 更多