2016-05-12 5 views
4
Group  Start   End    Days 
A   5/12/2015  5/14/2015  3 
A   5/12/2015  5/14/2015  3 
B   1/1/2015   1/3/2015  3 
B   1/1/2015   1/3/2015  3 
H   1/8/2015   1/9/2015  2 
H   1/8/2015   1/9/2015  2 
H   1/13/2015  1/15/2015  3 
H   1/7/2015   1/17/2015  3 
H   1/12/2015  1/22/2015  7 

Я приложил образец моего набора данных выше. Я пытаюсь подсчитать количество уникальных дней для каждой группы в R. Для некоторых наблюдений это довольно просто, т. Е. A и B. Однако есть несколько групп с различным перекрытием дней, а также пробелы в диапазонах дат, т.е. H.Подсчет уникальных дней с перекрытием и пробелами в диапазонах дат

Есть ли в любом случае я могу суммировать количество уникальных дней (не перекрывать и учитывать пробелы) для каждой группы в R? i.e A и B вернутся 3 дня соответственно, и H вернется 11 дней.

Group Count 
A  3 
B  3 
H  16 

Мое предположение было бы с помощью dplyr и суммировать функции, однако я не был в состоянии обернуть мою голову вокруг любого решения. Любая помощь приветствуется! Спасибо

+1

хорошо сформулированный вопрос. Не могли бы вы рассказать о том, как три случая должны суммироваться до 11 – OdeToMyFiddle

+0

Мои извинения, что правильный счет должен был быть 16, как указано ниже! –

ответ

5

Вот dplyr решение:

library(dplyr) 

df %>% 
    group_by(Group,rn = row_number()) %>% 
    do(data.frame(.,Date = seq(as.Date(.$Start,format = '%m/%d/%Y'), 
           as.Date(.$End,format = '%m/%d/%Y'), 
           '1 day'))) %>% 
    group_by(Group) %>% 
    summarise(numDays = n_distinct(Date)) 

Идея заключается в том, чтобы создать новый столбец, который содержит последовательность дат от начала до конца, а затем подсчитайте длину уникальных наблюдений в каждой группе.

Это дает:

Group numDays 
    (fctr) (int) 
1  A  3 
2  B  3 
3  H  16 
+0

Это сработало! Это беспокоило меня в течение нескольких дней, пока я не решил сделать учетную запись здесь. Вы, ребята, потрясающие! –

+0

Вы также можете использовать 'n_distinct' вместо' length' & 'unique' combo:' numDays = n_distinct (Date) ' – Jaap

+0

Спасибо за предложение @ProcrastinatusMaximus! Я обновил ответ, чтобы использовать n_distinct. – shreyasgm

4

Если вы хотите подсчитывать уникальные дни от группы, я хотел бы сделать (предполагая, что ваши Start и End столбцов в дата-формате):

library(data.table) 
setDT(mydf)[, .(dates = seq.Date(Start,End,'day')) , by = .(Group,1:nrow(mydf)) 
      ][, .(count = uniqueN(dates)), by = Group][] 

, который дает:

Group count 
1:  A  3 
2:  B  3 
3:  H 16 

Пояснение: Для каждой строки вы создаете последовательности дат с датами Start и End. После этого вы считаете уникальные дни функцией uniqueN. Это лучше, чем мой старый ответ (см. Ниже), потому что это учитывает пробелы.

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


Аналогичное решение с основанием R:

l <- mapply(seq.Date, mydf$Start, mydf$End, 1) 
df2 <- data.frame(group = rep(mydf$Group,sapply(l,length)), 
        dates = unlist(l)) 
aggregate(dates ~ group, df2, function(x) length(unique(x))) 

, который дает аналогичный результат:

group dates 
1  A  3 
2  B  3 
3  H 16 

Если вы хотите dates столбец в df2 в дата-формате, использовать as.Date(unlist(l), origin = '1970-01-01') вместо от unlist(l).


Б данные:

mydf <- structure(list(Group = c("A", "A", "B", "B", "H", "H", "H", "H", "H"), 
         Start = structure(c(16567, 16567, 16436, 16436, 16443, 16443, 16448, 16442, 16447), class = "Date"), 
         End = structure(c(16569, 16569, 16438, 16438, 16444, 16444, 16450, 16452, 16457), class = "Date"), 
         Days = c(3L, 3L, 3L, 3L, 2L, 2L, 3L, 3L, 7L)), 
        .Names = c("Group", "Start", "End", "Days"), row.names = c(NA, -9L), class = "data.frame") 
+0

Большое спасибо за подробное объяснение! Я очень ценю это! –

+0

@MichaelLuu Я также включил базовый подход R. – Jaap

Смежные вопросы