#r #dplyr
Вопрос:
У меня есть длинный список, в котором нужны дни между датами
ClientID <- c("00932", "00932", "00932")
Visit <- c("2018-11-10", "2018-11-20", "2018-11-25")
ClientID Visit
00932 2018-11-10
00932 2018-11-20
00932 2018-11-25
Мне нужна новая колонка, в которой говорится:
ClientID Visit Days
00932 2018-11-10 0
00932 2018-11-20 10
00932 2018-11-25 15
Ответ №1:
Измените Visit
класс на дату и для каждого ClientID
вычтите значение Visit
с минимальной Visit
датой.
library(dplyr)
df %>%
mutate(Visit = as.Date(Visit, '%m-%d-%Y')) %>%
group_by(ClientID) %>%
mutate(Days = as.integer(Visit - min(Visit))) %>%
ungroup
# ClientID Visit Days
# <chr> <date> <int>
#1 00932 2018-11-10 0
#2 00932 2018-11-20 10
#3 00932 2018-11-25 15
данные
ClientID <- c("00932", "00932", "00932")
Visit <- c("11-10-2018", "11-20-2018", "11-25-2018")
df <- data.frame(ClientID, Visit)
Комментарии:
1. Это решение создает 2 пустых столбца в моем фрейме данных, как посещение, так и Дни не являются N/A
2. Это прекрасно работает, используя данные в моем посте.
Ответ №2:
Учитывая, что у вас их несколько ClientID
и вы хотите рассчитать Days
на этом уровне:
library(lubridate)
library(tidyverse)
ClientID <- c("00932", "00932", "00932")
Visit <- c("11-10-2018", "11-20-2018", "11-25-2018")
df <- data.frame(ClientID, Visit)
df %>%
group_by(ClientID) %>%
mutate(Visit= mdy(Visit),
Days= as.numeric(Visit-lag(Visit)))%>%
ungroup()%>%
mutate_if(is.numeric, ~replace_na(., 0))
# A tibble: 3 x 3
ClientID Visit Days
<chr> <date> <dbl>
1 00932 2018-11-10 0
2 00932 2018-11-20 10
3 00932 2018-11-25 5
Добавим еще ClientID
одно и два наблюдения, чтобы лучше это продемонстрировать:
ClientID <- c("00932", "00932", "00932", "00935", "00935")
Visit <- c("11-10-2018", "11-20-2018", "11-25-2018", "11-20-2019", "11-25-2019")
df <- data.frame(ClientID, Visit)
df %>%
group_by(ClientID) %>%
mutate(Visit= mdy(Visit),
Days= as.numeric(Visit-lag(Visit)))%>%
ungroup()%>%
mutate_if(is.numeric, ~replace_na(., 0))
# A tibble: 5 x 3
ClientID Visit Days
<chr> <date> <dbl>
1 00932 2018-11-10 0
2 00932 2018-11-20 10
3 00932 2018-11-25 5
4 00935 2019-11-20 0
5 00935 2019-11-25 5
Добавление функции, как было предложено в комментариях:
days_func <- function(df){
df %>%
group_by(ClientID) %>%
mutate(Visit= mdy(Visit),
Days= as.numeric(Visit-lag(Visit)))%>%
ungroup()%>%
mutate_if(is.numeric, ~replace_na(., 0))->df
return(df)
}
df1 <- days_func(df)
df1
# A tibble: 3 x 3
ClientID Visit Days
<chr> <date> <dbl>
1 00932 2018-11-10 0
2 00932 2018-11-20 10
3 00932 2018-11-25 5
Комментарии:
1. Как я могу преобразовать это в функцию? Столбец «Дни» не может быть добавлен, если я попытаюсь превратить это в функцию
2. @RandomPerson Я добавил его. Проверять.
3. @RandomPerson это решило вашу цель?
Ответ №3:
Поскольку я предполагаю, что вам нужен промежуток времени между датами, а не между датой и последней датой, я предлагаю это:
dn <- as.numeric(as.Date(Visit))
Текст с датами последовательно преобразуется в дату и в число.
dn2 <- c(dn[1], dn[-length(dn)])
Мы готовим второй вектор для вычитания, так как он будет работать быстро. В нем будет такой порядок участников, как этот:
df df2
1-й 1-й
2-й 1-й
3-й 2-й
n-й n-й-1
Days <- dn - dn2
Найдите пролет.