在排列好的数据上使用 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)
这个解决方案有两个假设:
- 行按
id
排序。您可以使用 group_by(id)
后跟 ungroup()
语句来绕过这个假设,如 Maurits Evers 的解决方案中所示。
- 对于每个 id,具有观察日期的行在组中排在第一位。在任何情况下,
na.locf
和 fill
都必须如此,因为这两个函数都使用先前的非 NA 条目填充 NA。
如果您不想对排序做出任何假设,您可以在开头对行进行排序 data %>% arrange(id, dates)
。
我正在处理类似于
的数据集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)
这个解决方案有两个假设:
- 行按
id
排序。您可以使用group_by(id)
后跟ungroup()
语句来绕过这个假设,如 Maurits Evers 的解决方案中所示。 - 对于每个 id,具有观察日期的行在组中排在第一位。在任何情况下,
na.locf
和fill
都必须如此,因为这两个函数都使用先前的非 NA 条目填充 NA。
如果您不想对排序做出任何假设,您可以在开头对行进行排序 data %>% arrange(id, dates)
。