在排列好的数据上使用 mutate() 中的滞后

Using lag in mutate() on a arranged data

我正在处理类似于

的数据集
data <-tribble(
  ~id, ~ dates, ~days_prior,
  1,20190101, NA,
  1,NA, 15,
  1,NA, 20,
  2, 20190103, NA,
  2,NA, 3,
  2,NA, 4)

我有每个 ID 的第一个日期,我试图通过将 days_prior 添加到前一个日期来计算下一个日期。我正在使用滞后函数来引用前一个日期。

 df<- df%>% mutate(dates = as.Date(ymd(dates)), days_prior =as.integer(days_prior))


 df<-df %>% mutate(dates =
   as.Date(ifelse(is.na(days_prior),dates,days_prior+lag(dates)),
   origin="1970-01-01"))

这有效,但仅适用于下一行,您可以看到附加数据。

我做错了什么?我希望所有日期都由 mutate() 计算。我应该采用什么不同的方法来计算这个。

我真的不明白 lag 在这里有什么帮助;除非我误解这里是使用 tidyr::fill

的选项
data %>%
    group_by(id) %>%
    mutate(dates = as.Date(ymd(dates))) %>%
    fill(dates) %>%
    mutate(dates = dates + if_else(is.na(days_prior), 0L, as.integer(days_prior))) %>%
    ungroup()
## A tibble: 6 x 3
#     id dates      days_prior
#  <dbl> <date>          <dbl>
#1     1 2019-01-01         NA
#2     1 2019-01-16         15
#3     1 2019-01-21         20
#4     2 2019-01-03         NA
#5     2 2019-01-06          3
#6     2 2019-01-07          4

或略有变化,将 days_prior 中的 NA 条目替换为 0

data %>%
    group_by(id) %>%
    mutate(
        dates = as.Date(ymd(dates)),
        days_prior = replace(days_prior, is.na(days_prior), 0)) %>%
    fill(dates) %>%
    mutate(dates = dates + as.integer(days_prior)) %>%
    ungroup()

更新

针对您在评论中的说明,您可以执行以下操作

data %>%
    group_by(id) %>%
    mutate(
        dates = as.Date(ymd(dates)),
        days_prior = replace(days_prior, is.na(days_prior), 0)) %>%
    fill(dates) %>%
    mutate(dates = dates + cumsum(days_prior)) %>%
    ungroup()
## A tibble: 6 x 3
#     id dates      days_prior
#  <dbl> <date>          <dbl>
#1     1 2019-01-01          0
#2     1 2019-01-16         15
#3     1 2019-02-05         20
#4     2 2019-01-03          0
#5     2 2019-01-06          3
#6     2 2019-01-10          4

您可以使用 zoo 包中的 na.locf 在添加前几天之前填写最后观察到的日期。

library("tidyverse")
library("zoo")
data %>%
  # Fill in NA dates with the previous non-NA date
  # The `locf` stands for "last observation carried forward"
  # Fill in NA days_prior with 0
  mutate(dates = zoo::na.locf(dates),
         days_prior = replace_na(days_prior, 0)) %>%
  mutate(dates = lubridate::ymd(dates) + days_prior)

这个解决方案有两个假设:

  1. 行按 id 排序。您可以使用 group_by(id) 后跟 ungroup() 语句来绕过这个假设,如 Maurits Evers 的解决方案中所示。
  2. 对于每个 id,具有观察日期的行在组中排在第一位。在任何情况下,na.locffill 都必须如此,因为这两个函数都使用先前的非 NA 条目填充 NA。

如果您不想对排序做出任何假设,您可以在开头对行进行排序 data %>% arrange(id, dates)