Создание последовательности дат в R по группам, зависящих от другой переменной - PullRequest
2 голосов
/ 31 января 2020

Прямо сейчас мой набор данных находится в широком формате, то есть у меня одна строка на человека, но я хочу длинный набор данных с несколькими строками на человека. У меня есть две переменные даты, ADATE и DDATE, которые я хочу использовать в качестве начальной и конечной точек соответственно. Например, если у кого-то ADATE 02/04/10, а у DDATE 02/07/10, я хочу 4 строки:

Иметь:

ID ADATE     DDATE     
1  02/04/10  02/07/10 

Хочу:

ID ADATE     DDATE     NEW_DATE
1  02/04/10  02/07/10  02/04/10
1  02/04/10  02/07/10  02/05/10
1  02/04/10  02/07/10  02/06/10
1  02/04/10  02/07/10  02/07/10

У меня есть несколько наборов данных, для которых я хочу сделать это, и я написал код, который работает для каждого отдельного набора данных, кроме одного ... Я не уверен, почему. Это моя попытка и ошибка, которую я получаю:

jan15_long <- chf_jan15 %>%
  mutate(NEW_DATE = as.Date(ADATE)) %>%
  group_by(ID) %>%
  complete(NEW_DATE = seq.Date(as.Date(ADATE), as.Date(DDATE), by = "day")) %>%
  fill(vars) %>%
  ungroup()
Error in seq.Date(as.Date(ADATE), as.Date(DDATE), by = "day") : 
  'from' must be of length 1

Приведенный выше код дает мне то, что я хочу, и отлично работает для всех остальных наборов данных, которые у меня есть (10 из 11).

Есть ли лучший способ сделать это? dplyr имеет для меня наибольшее значение, так что, надеюсь, есть решение для этого.

1 Ответ

2 голосов
/ 31 января 2020

Если имеется более одной строки, seq необходимо зациклить. Мы можем использовать map2. Кроме того, на основе format столбцов «ДАТА» для as.Date требуется аргумент format, то есть as.Date(ADATE, "%m/%d/%y") (при условии, что это формат месяца / дня / года)

library(dplyr)
library(purrr)
library(lubridate)
chf_jan15 %>%
    mutate_at(vars(ends_with("DATE")), mdy) %>%
    mutate(random_date = map2(ADATE, DDATE, seq, by = "day")) %>%
    unnest(c(random_date))
# A tibble: 4 x 4
#     ID ADATE      DDATE      random_date
#  <int> <date>     <date>     <date>     
#1     1 2010-02-04 2010-02-07 2010-02-04 
#2     1 2010-02-04 2010-02-07 2010-02-05 
#3     1 2010-02-04 2010-02-07 2010-02-06 
#4     1 2010-02-04 2010-02-07 2010-02-07 

Если после преобразования в класс Date существует только одна строка, complete должен работать

library(tidyr)
chf_jan15 %>%
   mutate_at(vars(ends_with("DATE")), as.Date, format = "%m/%d/%y") %>%
   mutate(NEW_DATE = ADATE) %>%      
   complete(NEW_DATE = seq(ADATE, DDATE, by = 'day')) %>%
   fill(c(ID, ADATE, DDATE))
# A tibble: 4 x 4
#  NEW_DATE      ID ADATE      DDATE     
#  <date>     <int> <date>     <date>    
#1 2010-02-04     1 2010-02-04 2010-02-07
#2 2010-02-05     1 2010-02-04 2010-02-07
#3 2010-02-06     1 2010-02-04 2010-02-07
#4 2010-02-07     1 2010-02-04 2010-02-07

Если для каждого идентификатора есть отдельная строка, то мы можем group_split и использовать complete

chf_jan15 %>%
    mutate_at(vars(ends_with("DATE")), as.Date, format = "%m/%d/%y") %>%
    mutate(NEW_DATE = ADATE) %>%
    group_split(ID) %>%
    map_dfr(~ .x %>%
                 complete(NEW_DATE = seq(ADATE, DDATE, by = 'day')) %>%
                  fill(c(ID, ADATE, DDATE)))

data

chf_jan15 <- structure(list(ID = 1L, ADATE = "02/04/10", 
    DDATE = "02/07/10"), class = "data.frame", row.names = c(NA, 
-1L))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...