группировать и обобщать с условным диапазоном дат - dplyr? - PullRequest
0 голосов
/ 22 октября 2018

раскрытие - это мой первый вопрос, мои извинения, если это повторный вопрос, но я уже некоторое время искал и не нашел ответа на этот конкретный сценарий

R версия: 3.4.2

Я хочу эффективный способ группировки данных по определенному идентификатору, а затем суммировать на основе условия - динамически для каждой строки.В частности, сгруппируйте по идентификатору, а затем суммируйте, сколько экземпляров произошла другая переменная (срочные посещения), если другой экземпляр был в течение 1 года текущей строки.

Вот пример того, как должны выглядеть данные для начала:

Обновлено, чтобы включить пример 2 срочных дел

library(lubridate)
   > dat <- data.frame("ID" = c(6,6,6,7,7,10,11,11,11),
                      "Admit_Dt" = as.Date(c('2013-08-12', '2013-12-12', '2016-01-03','2011-04-01', '2011-09-20','2012-02-19','2014-06-24','2014-08-12','2014-09-01')), 
                      "Urgent" = c(0,1,1,1,0,0,1,1,1)) 
   > dat

| ID | Admit_Dt   | Urgent|
|  6 | 2013-08-12 |      1| 
|  6 | 2013-12-12 |      0|
|  6 | 2016-01-03 |      1|
|  7 | 2011-04-01 |      1|
|  7 | 2011-09-20 |      0|
| 10 | 2012-02-19 |      0|
| 11 | 2014-06-24 |      1|
| 11 | 2014-08-12 |      1|
| 11 | 2014-09-01 |      1|

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

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

   > dat$Urgent_1yrSum <- unlist(sapply(1:length(unique(dat$ID)), function(i) {
    grouped <-  subset(dat, ID == unique(dat$ID)[i])
      output <- do.call(rbind, lapply(1:nrow(grouped), function(y){
    urgent_sum_1year <- sum(grouped[grouped$Admit_Dt < grouped$Admit_Dt[y] & grouped$Admit_Dt > (grouped$Admit_Dt[y] - dyears(1)), "Urgent"])
     }))
      return(output)
}
))

> dat
| ID | Admit_Dt   | Urgent| Urgent_1yrSum|
|  6 | 2013-08-12 |      1|          0|
|  6 | 2013-12-12 |      0|          1|
|  6 | 2016-01-03 |      1|          0|
|  7 | 2011-04-01 |      1|          0|
|  7 | 2011-09-20 |      0|          1|
| 10 | 2012-02-19 |      0|          0|
| 11 | 2014-06-24 |      1|          0|
| 11 | 2014-08-12 |      1|          1|
| 11 | 2014-09-01 |      1|          2|

Спасибо за любую помощь !!

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Вот ответ, используя dplyr, столбцы списка и purrr.Я предполагаю, что нет дубликатов ID и Admit_Dt с, иначе я почти уверен, что это не работает правильно.

dat <- data.frame("ID" = c(6,6,6,7,7,10,11,11),
           "Admit_Dt" = c('2013-08-12', '2013-12-12', '2016-01-03','2011-04-01', '2011-09-20','2012-02-19','2014-06-24','2014-08-12'), 
           "Urgent" = c(0,1,1,1,0,0,1,1), stringsAsFactors = F)


library(dplyr)
library(purrr)
library(lubridate)

isUrgentAndWithinYear <- function(urgent, date, date1){
     sum( urgent == 1 & abs(as.numeric(difftime(date, date1, units = "weeks"))) < 52)
} 

dat %>%
     mutate(Admit_Dt = ymd(Admit_Dt)) %>% 
     group_by(ID) %>%
     mutate(urgents = list(Urgent),
            admits = list(Admit_Dt)
            )%>% 
     group_by(ID, Admit_Dt) %>% 
     mutate(Urgent_1yrSum = map2_dbl(urgents, admits, ~ isUrgentAndWithinYear(.x, .y, Admit_Dt) )) %>% 
     mutate(Urgent_1yrSum = Urgent_1yrSum - Urgent) %>% 
     select(-urgents, -admits)
0 голосов
/ 22 октября 2018

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

dat <- data.frame("ID" = c(6,6,6,7,7,10,11,11),
                  "Admit_Dt" = c('2013-08-12', '2013-12-12', '2016-01-03','2011-04-01', '2011-09-20','2012-02-19','2014-06-24','2014-08-12'), 
                  "Urgent" = c(0,1,1,1,0,0,1,1),stringsAsFactors = FALSE)
library(dplyr)


dat2 <- inner_join(dat,select(dat,ID,Admit_Dt,Urgent),by = "ID") %>% 
        #Inner Join by ID to get every combo of dates
        #Subtract dates from eachother 
        mutate(datediff = as.Date(Admit_Dt.x) - as.Date(Admit_Dt.y),
               ID = ID) %>%
        #get dates that occured within one year of visit
        #for each date
        filter(datediff > 0 & datediff <= 365) %>% 
        #group by person
        group_by(ID,Admit_Dt.x) %>% 
        #count urgent visits
       mutate(urgent_visits = max(Urgent.x,Urgent.y,na.rm=TRUE)) %>% 
    summarise(vs = sum(urgent_visits))
#Join back on to df

dat3 <- left_join(dat,dat2,by = c("ID" = "ID", "Admit_Dt"="Admit_Dt.x"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...