2009-12-07 24 views
10

Sto provando a rimodellare un frame di dati in R e sembra avere problemi usando i modi raccomandati di farlo. Il frame di dati ha la seguente struttura:R prestazioni con risagomatura dei dati

ID      DATE1    DATE2   VALTYPE  VALUE 
'abcd1233'   2009-11-12  2009-12-23   'TYPE1'  123.45 
... 

VALTYPE è una stringa ed è un fattore con solo 2 valori (diciamo TYPE1 e TYPE2). Ho bisogno di trasformarlo nei seguenti frame di dati ("wide" trasposizione) sulla base di ID comuni e le date:

ID      DATE1    DATE2   VALUE.TYPE1 VALUE.TYPE2 
'abcd1233'    2009-11-12  2009-12-23  123.45   NA 
... 

telaio I dati ha più di 4.500.000 osservazioni (anche se circa il 70% dei VALUE s sono NA). La macchina è una workstation Linux basata su Intel con 4 GB di RAM. Il caricamento dei dati (da un file Rdata compresso) in un nuovo processo R lo fa crescere fino a circa 250 Mb, il che lascia chiaramente molto spazio per la riformulazione.

Queste sono le mie esperienze finora:

  • Utilizzando vaniglia reshape() metodo:

    TBL2 < - rimodellare (TBL, direzione = "wide", idvar = c ("ID", "DATE1 "," DATE2 "), timevar =" VALTYPE ");

RISULTATO: Error: cannot allocate vector of size 4.8 Gb

  • Usando cast() metodo reshape pacchetto:

    TBL2 < - cast (TBL, ID + DATE1 + DATE2 ~ VALTYPE);

RISULTATO: processo R consuma tutta la RAM senza fine in vista. Dovevo uccidere il processo alla fine.

  • Utilizzando by() e merge():

    sp < - da (TBL [c (1,2,3,5)], tbl $ VALTYPE, la funzione (x) x); tbl < - unione (sp [["TYPE1"]], sp [["TYPE2"]], di = c ("ID", "DATA1", "DATA2"), tutto = TRUE, sort = TRUE) ;

RISULTATO: funziona bene, anche se questo non è molto elegante e infallibile (cioè si romperà se vengono aggiunti altri tipi).

Per aggiungere la beffa al danno, l'operazione in questione può essere banalmente realizzata in circa 3 righe di AWK o Perl (e con quasi nessuna RAM utilizzata). Quindi la domanda è: qual è un modo migliore per fare questa operazione in R usando i metodi raccomandati senza consumare tutta la RAM disponibile?

risposta

1

Un trucco utile consiste nel combinare le variabili id ​​in un vettore di caratteri e quindi eseguire la risagoma.

tbl$NEWID <- with(tbl, paste(ID, DATE1, DATE2, sep=";")) 
tbl2 <- recast(tbl2, NEWID ~ VALTYPE, measure.var="VALUE") 

Si tratta di circa il 40% più veloce in un problema di dimensioni simili nel mio Intel Core2 Duo 2.2GHz macbook.

+0

No, l'uso di 'recast()' mostra lo stesso problema del metodo 'cast()' sopra - il processo ha superato i 5 Gb di memoria virtuale, quindi l'ho ucciso dopo circa 1 ora. –

1

Che ne dici di fare questo in modo non simile a R? Presumo che tu abbia una riga TYPE1 e TYPE2 per ogni valore di ID, DATE1, DATE2? Quindi ordina il dataframe in base a tali variabili e scrivi un ciclo for big. Puoi eseguire ripetutamente operazioni rbind() per creare la tabella, oppure puoi provare a pre-allocare la tabella (forse) e assegnare solo gli slot VALUE.TYPE1 e VALUE.TYPE2 con [< -, che dovrebbe eseguire l'assegnazione in posto.

(Si noti che se si sta utilizzando rbind(), credo che è inefficiente se avete variabili fattore, in modo da assicurarsi che tutto è un personaggio, invece!)

+0

Senza 'rbind' e cicli:' tbl <- tbl [con (tbl, ordine (ID, DATE1, DATE2, VALTYPE)),]; tbl_out <- tbl [seq (1, nrow (tbl), di = 2), - 4]; nomi (tbl_out) [4] <- "VALUE.TYPE1"; tbl_out $ VALUE.TYPE2 <- tbl $ VALORE [seq (2, nrow (tbl), di = 2)]; ' – Marek

+0

Non possiamo davvero presumere che esistano esattamente 2 voci per ciascun ID/DATE. Questo infrangerà immediatamente il codice di Marek sopra. Inoltre, sarebbe ancora più fragile del mio codice 'by()/merge()' nel corpo della domanda. In generale, non ho alcun problema con l'approccio ad anello, tranne per il fatto che non capisco perché la funzione specificamente per quello scopo (cioè 'reshape()' fallisce su un problema così insignificante) –

1

Forse si potrebbe usare il gatto() funzione?

Problemi correlati