2016-11-01 5 views
0

Я пытаюсь вычислить скользящее число/количество вхождений по группе по серии временных рамок.Подсчет количества событий за все время

У меня есть фрейм данных с некоторыми образцами данных, как это:

dates = as.Date(c("2011-10-09", 
     "2011-10-15", 
     "2011-10-16", 
     "2011-10-18", 
     "2011-10-21", 
     "2011-10-22", 
     "2011-10-24")) 

group1=c("A", 
     "C", 
     "A", 
     "A", 
     "L", 
     "F", 
     "A") 
group2=c("D", 
     "A", 
     "B", 
     "H", 
     "A", 
     "A", 
     "E") 

df1 <- data.frame(dates, group1, group2) 

Я перебирать отдельные кадры данных для каждого уникального «группы», так, например, это то, как группа для «А» будет выглядеть (они присутствуют в каждой строке, будь то в группе 1 или группе2).

Я хочу рассчитывать на «A» (а затем каждую группу позже) количество событий в временном диапазоне - «дату» события (то есть текущую дату строки) и предыдущие 4 дня , Я хочу перевернуть это вперед, так что, например, строка 1 имела бы счет 1, строка 2 также имела бы счет 1 (за последние 4 дня не было событий, кроме указанной даты), строка 3 имела бы 2 строки 4 будет иметь 3 и т. Д.

Для каждой строки я хотел бы получить столбец, который в основном говорит, что в эту дату события есть X количество событий, которые произошли на настоящую дату (как указано в столбец даты) и за последние 4 дня.

+0

Вы можете обернуть 'дату <- as.Date (с (...))' поэтому у вас есть правильная дата вместо строки в примере. – Frank

+0

Не могли бы вы привести пример желаемого результата для этих данных? Мне непонятно, что именно вы ищете. – Barker

ответ

3

Для этого примера, вы можете, вероятно, использовать sapply анализировать каждую строку, подсчет количества записей в этот день или до 4-х дней раньше, например, так:

df1$lastFour <- 
    sapply(df1$dates, function(x){ 
    sum(df1$dates <= x & df1$dates >= x - 4) 
    }) 

Результаты в df1 из:

 dates group1 group2 lastFour 
1 2011-10-09  A  D  1 
2 2011-10-15  C  A  1 
3 2011-10-16  A  B  2 
4 2011-10-18  A  H  3 
5 2011-10-21  L  A  2 
6 2011-10-22  F  A  3 
7 2011-10-24  A  E  3 

Если, как следует из вашего вопроса, ваши данные из большего набора, и вы хотите, чтобы сделать анализ по каждой группе (концептуально, я думаю, вопрос в том: сколько событий было этой группа в л четыре дня? заданные только в дни с событием из этой группы), вы можете выполнить следующие шаги.

Во-первых, здесь некоторые большие выборки данных с помощью групп помечены как первые 10 букв алфавита:

biggerData <- 
    data.frame(
    dates = sample(seq(as.Date("2011-10-01") 
         , as.Date("2011-10-31") 
         , 1) 
        , 100, TRUE) 
    , group1 = sample(LETTERS[1:10], 100, TRUE) 
    , group2 = sample(LETTERS[1:10], 100, TRUE) 
) 

Далее извлечь все группы в данных (здесь, я их знаю, но для реальных данных, вы можете или не иметь, что список групп уже)

groupsInData <- 
    sort(unique(c(as.character(biggerData$group1) 
       , as.character(biggerData$group2)))) 

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

sepGroupCounts <- lapply(groupsInData, function(thisGroup){ 
    dfTemp <- biggerData[biggerData$group1 == thisGroup | 
         biggerData$group2 == thisGroup, ] 

    dfTemp$lastFour <- 
    sapply(dfTemp$dates, function(x){ 
     sum(dfTemp$dates <= x & dfTemp$dates >= x - 4) 
    }) 
    return(dfTemp) 

}) 

names(sepGroupCounts) <- groupsInData 

возвращает data.frame точно так же, как указано выше для каждой группы в ваших данных.

И, я не мог с собой поделать, поэтому здесь есть решение dplyr и tidyr. Он не сильно отличается от решения на основе списка выше, за исключением того, что он возвращает все в одном и том же файле data.frame (что может быть или не быть хорошим, особенно потому, что он будет иметь две записи для каждого события таким образом).

Во-первых, для простоты я определил функцию для проверки даты. Это можно было бы легко использовать и выше.

myDateCheckFunction <- function(x){ 
    sapply(x, function(thisX){ 
    sum(x <= thisX & x >= thisX - 4) 
    }) 
} 

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

dotsConstruct <- 
    paste0("group1 == '", groupsInData, "' | " 
     , "group2 == '", groupsInData, "'") %>% 
    setNames(groupsInData) 

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

withLastFour <- 
    # Start with data 
    biggerData %>% 
    # Add a col for each group using Standard Evaluation 
    mutate_(.dots = dotsConstruct) %>% 
    # convert to long form; one row per group per event 
    gather(GroupAnalyzed, Present, -dates, -group1, -group2) %>% 
    # Limit to only rows where the `GroupAnalyzed` is present 
    filter(Present) %>% 
    # Remove the `Present` column, as it is now all "TRUE" 
    select(-Present) %>% 
    # Group by the groups we are analyzing 
    group_by(GroupAnalyzed) %>% 
    # Add the column for count in the last four dates 
    # `group_by` limits this to just counts within that group 
    mutate(lastFour = myDateCheckFunction(dates)) %>% 
    # Sort by group and date for prettier checking 
    arrange(GroupAnalyzed, dates) 

Результат аналогичен приведенному выше list продукции, за исключением все в одном data.frame, что может позволить для облегчения анализа некоторых особенностей. Верх выглядит следующим образом:

 dates group1 group2 GroupAnalyzed lastFour 
     <date> <fctr> <fctr>   <chr> <int> 
1 2011-10-01  B  A    A  1 
2 2011-10-02  J  A    A  2 
3 2011-10-05  C  A    A  5 
4 2011-10-05  C  A    A  5 
5 2011-10-05  G  A    A  5 
6 2011-10-08  E  A    A  5 

Обратите внимание, что у моего случайного образца было несколько событий в октябре-05, что привело к большим подсчетам здесь.

1

Я думаю, но не уверен, что вы ищете способ подсчета вхождения каждого типа события (буквы) в каждую дату (строку) и предшествующие четыре дня, независимо от того, появляются ли те, которые предшествуют четыре дня в ваших данных. Если это так, то вот один подход, используя dplyr (для общего удобства), tidyr (чтобы сделать данные длиннее для более удобного подсчета по дате) и zoo (для его функции rollapply).

library(dplyr) 
library(tidyr) 
library(zoo) 

df2 <- df1 %>% 
    # make the wide data long so we can group and then count by date 
    gather(key = group, value = event, group1:group2) %>% 
    # group by date 
    group_by(dates) %>% 
    # count occurrences of the event of interest on each date 
    summarise(sum.a = sum(event == "A")) %>% 
    # join that set of counts to a complete date sequence 
    left_join(data.frame(dates = seq(first(dates), last(dates), by = "day")), .) %>% 
    # use rollapply to get sums of those counts across rolling windows that 
    # are 4 days wide and right-aligned 
    mutate(sum.a = rollapply(sum.a, width = 4, sum, na.rm = TRUE, 
           partial = TRUE, align = "right")) %>% 
    # filter back to the original set of dates in df1 
    filter(dates %in% df1$dates) 

Результат:

> df2 
     dates sum.a 
1 2011-10-09  1 
2 2011-10-15  1 
3 2011-10-16  2 
4 2011-10-18  3 
5 2011-10-21  2 
6 2011-10-22  2 
7 2011-10-24  3 

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

  • Нет связанных вопросов^_^