Перекрывающиеся периоды, группирующие действия по идентификаторам с R - PullRequest
0 голосов
/ 03 апреля 2019

У меня есть набор данных с идентификаторами, начальной датой, конечной датой, статусом активности.Текущий набор данных насчитывает 150 000 строк и 50 000 идентификаторов, но будет намного больше.

Я бы хотел, чтобы R перегруппировалась в одну и ту же строку для одного и того же идентификатора и тех же периодов (даты начала и окончания), разныхдействия, происходящие в перекрывающийся период.

Другими словами, я пытаюсь: 1) изменить форму данных, чтобы получить перекрывающиеся и непересекающиеся периоды в определенных строках.2) склеивание перекрывающегося статуса активности.

Я уже пробовал:

Найти перекрывающиеся даты для каждого идентификатора и создать новую строку для перекрытия

и

Преобразование данных перекрывающихся временных диапазонов в данные различных временных диапазонов

Оба эти решения очень хороши и очень мне помогли.

Однако эти два подхода не могут обрабатывать в один кусок весь набор данных из 150 000 строк.Я использовал второе решение, разделив мой набор данных.Мне понадобилось 2 часа, чтобы проанализировать 18 000 строк.

Интересно, может ли какое-нибудь решение быть более эффективным на R. Я думал об использовании mutate, но я не очень знаком с этой функцией.

Входные данные выглядят так:

ID  START   END STATUS  
5c0e83  2013-11-01  2015-01-01  P1  
5c0e83  2002-09-01  2003-09-01  F2  
5c0e83  2016-09-01  2016-09-01  F0  
5c0e83  2006-01-01  2007-01-01  P3  
5c0e83  2003-11-01  2013-11-01  P2  
5c0e83  2015-09-01  2018-01-01  P0  
5c0e83  2003-09-01  2005-09-01  F1  

Благодаря ранее процитированному сценарию выходные данные были такими ( Преобразование данных перекрывающихся временных диапазонов в данные различных временных диапазонов )

ID  STATUS  START   END
5c0e83  F3  2002-09-01  2002-09-01
5c0e83  F3  2002-09-01  2002-10-01
5c0e83  F3  2002-10-01  2002-10-01
5c0e83  F3  2002-10-01  2002-11-01
5c0e83  F3  2002-11-01  2002-11-01
5c0e83  F3  2002-11-01  2003-01-01
5c0e83  F3  2003-01-01  2003-01-01
5c0e83  F3  2003-01-01  2003-09-01
5c0e83  F3, F2  2003-09-01  2003-09-01
5c0e83  F2  2003-09-01  2003-10-01
5c0e83  F2  2003-10-01  2003-10-01
5c0e83  F2  2003-10-01  2003-11-01
5c0e83  F2, P2  2003-11-01  2003-11-01
5c0e83  F2, P2  2003-11-01  2004-01-01
5c0e83  F2, P2  2004-01-01  2004-01-01
5c0e83  F2, P2  2004-01-01  2004-09-01
5c0e83  F2, P2  2004-09-01  2004-09-01
5c0e83  F2, P2  2004-09-01  2004-10-01
5c0e83  F2, P2  2004-10-01  2004-10-01
5c0e83  F2, P2  2004-10-01  2004-11-01

Результат хорошийно время для лечения очень долго.Интересно, думает ли кто-нибудь о более эффективном способе выполнения этой задачи.

Спасибо за вашу помощь

Ответы [ 2 ]

0 голосов
/ 04 апреля 2019

Спасибо за вашу помощь.

Ваше решение обеспечивает огромный выигрыш времени. С 2 часов я опускаюсь до нескольких секунд, чтобы обработать 12.000 строк.

Однако, когда я загружаю больший кадр данных (150 000 строк), я получаю следующую ошибку:

Ошибка: по оценкам 3040980.62465753 возвращаемых строк, больше 1 миллиона в break_above

Traceback: 1. df_ml2%>% сборки (тип, дата, START, END)%>% group_by (ID, STATUS)%>% padr :: pad (group = c ("ID", "STATUS"), интервал = "1 месяц ")%>% отличный (ID, STATUS, дата)%>% group_by (ID, дата)%>% суммировать (STATUS = вставить (уникальный (STATUS), свернуть = ","))%>% mutate (type = case_when (row_number () ==

1 | STATUS! = Задержка (STATUS) ~ "START", row_number () == n () | STATUS! = Lead (STATUS) ~ "END", TRUE ~ NA_character_))%>% фильтра (! Is.na (тип) )%>% group_by (ID, STATUS)%>% mutate (цикл = cumsum (тип ==) «START»))%>% ungroup ()%>% спред (тип, дата)%>% mutate (END = if_else (is.na (END), START, END)) 2. withVisible (eval (цитата (_fseq (_lhs)), env, env))

  1. eval (цитата (_fseq (_lhs)), env, env)

  2. eval (цитата (_fseq (_lhs)), env, env)

  3. _fseq (_lhs)

  4. freduce (значение, _function_list)

  5. function_list [я]

  6. padr :: pad (., Group = c ("ID", "STATUS"), интервал = "1 месяц")

  7. break_above_func (return_rows, break_above)

  8. stop (sprintf («Оценено% s возвращенных строк, больше% s миллиона в break_above», n, порог), вызов. = FALSE)

Решение состоит в том, чтобы применить сценарий к списку наборов данных, или есть способ выйти за пределы миллиона разломов?

Еще раз спасибо за вашу помощь.

0 голосов
/ 03 апреля 2019

Это немного быстрее, чем решение, которое вы связали с в данных выборки, но я надеюсь, что значительно быстрее для ваших больших данных.

Мой подход состоял в том, чтобы привести данные в длинную форму, заполнить каждое значение ID-STATUS, чтобы получить строку для каждого месяца в диапазоне, затем получить комбинации для каждой даты-идентификатора, затем извлечь START и END каждой комбинации и снова широко разложи.

library(tidyverse)
df2 <- df %>%
  gather(type, date, START, END) %>%
  group_by(ID, STATUS) %>%
  padr::pad(group = c("ID", "STATUS"), interval = "1 month") %>%
  distinct(ID, STATUS, date) %>%  # For statuses that only last 1 month, only need one row, not both

  # Adapted from https://stackoverflow.com/questions/52010252/convert-data-of-overlapping-time-ranges-to-data-of-distinct-time-ranges/52011136#52011136
  group_by(ID, date) %>%
  summarize(STATUS = paste(unique(STATUS), collapse = ", ")) %>%

  mutate(type = case_when(row_number() == 1   | STATUS != lag(STATUS)  ~ "START",
                          row_number() == n() | STATUS != lead(STATUS) ~ "END",
                          TRUE  ~ NA_character_)) %>%
  filter(!is.na(type)) %>%

  # This last part is to reshape the data to be wide again, with the first line
  #   to keep re-introduced combinations distinct from prior occurences
  group_by(ID, STATUS) %>% mutate(cycle = cumsum(type == "START")) %>% ungroup() %>%
  spread(type, date) %>%
  mutate(END = if_else(is.na(END), START, END)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...