我正在处理类似于的数据集
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
或稍微变化,将NA
中的days_prior
条目替换为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
您可以使用na.locf
包中的zoo
填写最后观察日期,然后再添加前几天。
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)
该解决方案有两个假设:
id
排序。您可以使用group_by(id)
以及随后的Mauriz Evers解决方案中的ungroup()
声明来解决这个假设。na.locf
和fill
,因为两个函数都使用先前的非NA条目填充NA。如果您不想对排序做出任何假设,可以使用data %>% arrange(id, dates)
对开头的行进行排序。