2015-01-28 3 views
7

Вот мой исходный кадр данных:R: Как просуммировать на основе нескольких критериев и обобщать таблица

df <- read.table(text=" 
    Date   Index Event 
    2014-03-31 A  x 
    2014-03-31 A  x 
    2014-03-31 A  y 
    2014-04-01 A  y 
    2014-04-01 A  x 
    2014-04-01 B  x 
    2014-04-02 B  x 
    2014-04-03 A  x 
    2014-09-30 B  x", header = T, stringsAsFactors = F) 

date_range <- seq(as.Date(min(df$Date)), as.Date(max(df$Date)), 'days') 
indices <- unique(df$Index) 
events_table <- unique(df$Event) 

Я хочу, чтобы мой желаемый результат, чтобы суммировать мои dataframe и имеет уникальную запись для каждого индекса в индексах и каждая дата в date_range, предоставляя кумулятивное значение каждого события в event_table в новом столбце для всех дат, предшествующих значению в столбце «Дата». Иногда нет записей для каждого индекса или каждой даты.

Вот мой желаемый результат:

Date  Index cumsum(Event = x) cumsum(Event = y) 
2014-03-31 A  0     0 
2014-03-31 B  0     0 
2014-04-01 A  2     1 
2014-04-01 B  0     0 
2014-04-02 A  3     2 
2014-04-02 B  1     0 
... 
2014-09-29 A  4     2 
2014-09-29 B  2     0 
2014-09-30 A  4     2 
2014-09-30 B  2     0 

FYI - это упрощенная версия фрейма данных. Есть ~ 200 000 записей в год с сотнями различных полей Индекса для каждой Даты.

Я делал это в прошлом, прежде чем мой жесткий диск обжарил, используя by и, возможно, aggregate, но процесс был очень медленным, и я не смог его обработать на этот раз. Я также пробовал ddply, но я не могу получить функцию cumsum для работы с ней. Используя ddply, я пытался что-то вроде:

ddply(xo1, .(Date,Index), summarise, 
     sum.x = sum(Event == 'x'), 
     sum.y = sum(Event == 'y')) 

безрезультатно.
Через поиск, я нашел Replicating an Excel SUMIFS formula , который доставит мне кумулятивную часть моего проекта, но с этим я не смог понять, как суммировать его до одной записи на дату/индексную комбинацию. Я также наткнулся на sum/aggregate data based on dates, R, но здесь я не смог обработать динамическую дату.

Спасибо всем, кто может помочь!

+0

Я смущен вашим ожидаемым выходом. В одной строке вашего ожидаемого результата вы ожидаете, что 'cumsum (Event = x)' будет '0'? Даже если ваш исходный 'df' имеет 2 строки с' Date = 2014-03-31', 'Index = A' и' Event = x'? – davechilders

+0

Добавление подчеркивания «Я хочу, чтобы мой желаемый результат суммировал мой фрейм данных и имел уникальную запись для каждого индекса в индексах и каждую дату в date_range, одновременно предоставляя кумулятивное значение каждого события в event_table в новом столбце ** для всех дат до Столбец даты ** « ... Для фона я пытаюсь создать модель, используя информацию, которая была бы доступна мне в то утро. Итак, утром 2014-03-31 у меня нет данных.В течение дня собираются данные, а в 2014-04-01 данные от 2014-03-31 - это то, что я буду иметь, чтобы прогнозировать события на 2014-04-01 – exhoosier10

+0

Спасибо за разъяснение. Я пропустил это при первом чтении. – davechilders

ответ

3
library(dplyr) 
library(tidyr) 

df$Date <- as.Date(df$Date) 

Шаг 1: Создайте полный список {Дата, индекс} пар

full_dat <- expand.grid(
    Date = date_range, 
    Index = indices, 
    stringsAsFactors = FALSE 
) %>% 
    arrange(Date, Index) %>% 
    tbl_df 

Шаг 2: Определить cumsum() функцию, которая игнорирует NA

cumsum2 <- function(x){ 

    x[is.na(x)] <- 0 
    cumsum(x) 

} 

Шаг 3 : Генерировать итоговые значения по {Дате, Индексу}, объединяться с полными {Датами, Индексами} данными, и вычислять l суммарная сумма.

df %>% 
    group_by(Date, Index) %>% 
    summarise(
    totx = sum(Event == "x"), 
    toty = sum(Event == "y") 
    ) %>% 
    right_join(full_dat, by = c("Date", "Index")) %>% 
    group_by(Index) %>% 
    mutate(
    cumx = lag(cumsum2(totx)), 
    cumy = lag(cumsum2(toty)) 
    ) %>% 
    # some clean up. 
    select(-starts_with("tot")) %>% 
    mutate(
    cumx = ifelse(is.na(cumx), 0, cumx), 
    cumy = ifelse(is.na(cumy), 0, cumy) 
    ) 
+0

блестящий. взял <10 секунд для этих 200 тыс. строк. Ценю вашу помощь! – exhoosier10

1

Будет что-то вроде этого с помощью dplyr и tidyr работы?

library(dplyr) 
library(tidyr) 

df %>% 
    group_by(Date, Index, Event) %>% 
    summarise(events = n()) %>% 
    group_by(Index, Event) %>% 
    mutate(cumsum_events = cumsum(events)) %>% 
    select(-events) %>% 
    spread(Event, cumsum_events) %>% 
    rename(sum.x = x, 
     sum.y = y) 

#  Date Index sum.x sum.y 
#1 2014-03-31  A  2  1 
#2 2014-04-01  A  3  2 
#3 2014-04-01  B  1 NA 
#4 2014-04-02  B  2 NA 
#5 2014-04-03  A  4 NA 
#6 2014-09-30  B  3 NA 
+0

Умное использование 'spread()' здесь. +1 –

+0

Это полезно, чтобы суммировать все, спасибо .... Моя цель состояла в том, чтобы иметь одну запись для каждого уникального индекса (все индексы) и даты (даты между 2014-03-31 и 2014-09-30) что я могу экспортировать это в отдельный файл за каждый день всех данных года до этого момента. В некоторые дни мы не собираем информацию об индексе A, поэтому, если я подмножусь по дате = '2014-04-02', используя этот метод, я бы видел только данные для индекса B, а не A. Есть ли какой-либо быстрый способ получить что без добавления дополнительных нулевых записей для каждого уникального ключа Date + Index? – exhoosier10

+0

@maloneypatr - Я не думаю, что ваше решение соответствует желаемому результату OP. – davechilders

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