Есть ли способ заполнить недостающие даты нулями с помощью dplyr?

У меня есть такой набор данных:

id  date     value      
1   8/06/12    1         
1   8/08/12    1         
2   8/07/12    2         
2   8/08/12    1         

Каждый идентификатор должен иметь значение для каждой даты. Если в идентификаторе отсутствует определенная дата, эту строку необходимо добавить со значением 0. Например,

id  date     value      
1   8/06/12    1   
1   8/07/12    0      
1   8/08/12    1  
2   8/06/12    0         
2   8/07/12    2         
2   8/08/12    1     

Я пытаюсь понять, как добавить строки с 0 с. Здесь есть хорошее решение: R - заполнить пропущенные даты по группам. Однако я не могу использовать функцию tidyr::complete, потому что я использую sparklyr и, насколько я знаю, должен оставаться в рамках dplyr функций.


person Jacob Curtis    schedule 23.01.2019    source источник
comment
Полный временной ряд с помощью sparklyr   -  person 10465355    schedule 23.01.2019


Ответы (2)


В sparklyr необходимо использовать функции Spark. Это работа для coalesce. Сначала вам нужно заполнить все пары идентификаторов и дат, которые вы ожидаете увидеть, например, что-то вроде: (изменить)

all_id <- old_data %>% distinct(id) %>% mutate(common=0)
all_date <- old_data %>% distinct(date) %>% mutate(common=0)
all_both <- all_id %>% full_join(all_date,by='common')
data <- old_data %>%
  right_join(all_both %>% select(-common),by=c('id','date')) %>%
  mutate(value=`coalesce(value,0)`)

Я предположил, что у вас есть все даты и идентификаторы, которые вам нужны, в ваших старых данных, хотя это может быть не так.

person steveo'america    schedule 23.01.2019
comment
Я могу создать таблицу всех необходимых дат. Я собираюсь попробовать это прямо сейчас. Спасибо за быстрый ответ! - person Jacob Curtis; 23.01.2019
comment
Теперь, когда я думаю об этом, мой код не будет делать именно то, что вы хотите; вам нужно правильно присоединиться ко всем датам и идентификаторам... - person steveo'america; 23.01.2019
comment
Попался. Я изменю это. - person Jacob Curtis; 23.01.2019
comment
full_join кажется более безопасным, чем right_join, просто на случай, если в all_date пропущены даты, они не будут удалены молча. - person Gregor Thomas; 23.01.2019
comment
Мой девиз Sparklyr: в двенадцатый раз - прелесть. - person steveo'america; 23.01.2019
comment
Когда я тестирую full_join, я получаю сообщение об ошибке, потому что нет общих переменных. Что мне не хватает? - person Jacob Curtis; 23.01.2019
comment
Отличное решение. Но я думаю, что третья строка кода (full_join) не будет работать, потому что all_id и all_date не имеют общих переменных. - person Darren Tsai; 23.01.2019
comment
Думаю, я могу просто добавить общую переменную для полного соединения. например, all_id ‹- old_data %›% отличные(идентификатор) %›% dplyr::mutate(join_placeholder = 1) all_date ‹- old_data %›% отличные(дата) %›% dplyr::mutate(join_placeholder = 1). я собираюсь попробовать это - person Jacob Curtis; 23.01.2019
comment
Вы правы. Отредактировано снова, чтобы иметь общее поле. - person steveo'america; 23.01.2019

expand.grid()

Используйте expand.grid() для создания всех комбинаций id и date. Кстати, обратите внимание на преобразование вашей даты в класс Date на as.Date(), иначе это будет бессмысленная строка.

df %>% mutate(date = as.Date(date, "%m/%d/%y")) %>%
  right_join(expand.grid(id = unique(.$id), date = unique(.$date))) %>%
  mutate(value = coalesce(value, 0L)) %>% 
  arrange(id, date)

#   id       date value
# 1  1 2012-08-06     1
# 2  1 2012-08-07     0
# 3  1 2012-08-08     1
# 4  2 2012-08-06     0
# 5  2 2012-08-07     2
# 6  2 2012-08-08     1

Воспроизводимые данные

df <- structure(list(id = c(1L, 1L, 2L, 2L), date = c("8/06/12", "8/08/12", 
"8/07/12", "8/08/12"), value = c(1L, 1L, 2L, 1L)), class = "data.frame", row.names = c(NA, 
-4L))
person Darren Tsai    schedule 23.01.2019
comment
expand.grid будет хорошо работать на data.frame, но его придется копировать в spark. Я считаю, что волшебное заклинание для этого заключается в использовании параметра copy в соединении. Что-то вроде right_join(my_local_df,by=..., copy=TRUE). - person steveo'america; 23.01.2019
comment
Спасибо за ваше отличное предложение! Я не заметил этого, пока не увидел твой комментарий. - person Darren Tsai; 23.01.2019