2015-01-28 9 views
7

Ecco il mio frame di dati originali:R: come riassumere in base a più criteri e riassumere tavolo

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) 

voglio che il mio output desiderato per riassumere il mio dataframe e hanno un record unico per ogni indice in indici e ogni data in date_range fornendo un valore cumulativo di ciascun evento in events_table in una nuova colonna per tutte le date precedenti al valore nella colonna Data. A volte non ci sono record per ogni indice o ogni data.

Ecco il mio risultato desiderato:

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 

CRONACA - questa è una versione semplificata del frame di dati. Ci sono ~ 200.000 record all'anno con centinaia di diversi campi Indice per ogni Data.

Ho fatto questo in passato prima che il mio disco rigido friggesse usando by e forse aggregate, ma il processo era molto lento e non sono in grado di farlo funzionare stavolta. Ho anche provato ddply, ma non sono in grado di ottenere la funzione cumsum per lavorare con esso. Utilizzando ddply, ho provato qualcosa di simile:

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

inutilmente. Attraverso la ricerca, ho trovato Replicating an Excel SUMIFS formula che mi ottiene la parte cumulativa del mio progetto, ma con questo non ero in grado di capire come riassumerlo in un solo record per combinazione data/indice. Mi sono imbattuto anche in sum/aggregate data based on dates, R ma qui non ero in grado di calcolare l'aspetto della data dinamica.

Grazie per tutti coloro che possono aiutare!

+0

Sono confuso dall'output previsto. In una riga dell'output atteso, ci si aspetta che 'cumsum (Event = x)' sia '0'? Anche se il tuo 'df' originale ha 2 righe con' Date = 2014-03-31', 'Index = A', e' Event = x'? – davechilders

+0

Aggiunta di enfasi "Desidero che l'output desiderato riepiloghi il mio dataframe e abbia un record univoco per ciascun indice in indici e ogni data in date_range fornendo un valore cumulativo di ciascun evento in events_table in una nuova colonna ** per tutte le date precedenti al Colonna della data ** " ...... Per lo sfondo, sto cercando di costruire un modello utilizzando le informazioni che sarebbero state disponibili per quella mattina. Quindi, la mattina del 2014-03-31, non ho dati disponibili.Durante il giorno, i dati vengono raccolti e, dal 2014-04-01, i dati del 2014-03-31 sono quelli che avrò a disposizione per prevedere gli eventi il ​​2014-04-01 – exhoosier10

+0

Grazie per i chiarimenti. L'ho perso nella mia prima lettura. – davechilders

risposta

3
library(dplyr) 
library(tidyr) 

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

Fase 1: Generare un elenco completo di {Data, index} coppie

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

Fase 2: Definire una funzione cumsum() che ignora NA

cumsum2 <- function(x){ 

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

} 

Fase 3 : Genera totali per {Data, Indice}, unisciti ai dati completi {Data, Indice}, e calcola il numero somma cumulata agganciata.

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

brillante. ha impiegato <10 secondi per queste righe da 200k. Apprezzo il tuo aiuto! – exhoosier10

1

Sarebbe qualcosa di simile utilizzando dplyr e tidyr lavoro?

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

L'uso intelligente di 'spread()' qui. +1 –

+0

Questo è utile per riassumere tutto, grazie .... Il mio obiettivo era quello di avere un record per ogni indice univoco (tutti gli indici) e Data (date tra 2014-03-31 e 2014-09-30) così combo che posso esportarlo in un singolo file per ogni giorno di tutti i dati dell'anno fino a quel momento. Alcuni giorni non raccogliamo informazioni sull'indice A, quindi se ho sottoinsieme per data = '2014-04-02' usando questo metodo, vedrei solo i dati per l'indice B e non A. C'è un modo rapido per ottenere senza aggiungere ulteriori record annullati per ogni chiave Data + Indice univoca ?? – exhoosier10

+0

@maloneypatr - Non penso che la tua soluzione corrisponda all'output desiderato dall'OP. – davechilders