2015-05-13 10 views
5

Ho un data.table in R che è stato recuperato da un database che assomiglia a questo:Fill in file mancante con R data.table

date,identifier,description,location,value1,value2 
2014-03-01,1,foo,1,100,200 
2014-03-01,1,foo,2,200,300 
2014-04-01,1,foo,1,100,200 
2014-04-01,1,foo,2,100,200 
2014-05-01,1,foo,1,100,200 
2014-05-01,1,foo,2,100,200 
2014-03-01,2,bar,1,100,200 
2014-04-01,2,bar,1,100,200 
2014-05-01,2,bar,1,100,200 
2014-03-01,3,baz,1,100,200 
2014-03-01,3,baz,2,200,300 
2014-04-01,3,baz,1,100,200 
2014-04-01,3,baz,2,100,200 
2014-05-01,3,baz,1,100,200 
2014-05-01,3,baz,2,100,200 
2014-05-01,4,quux,2,100,200 
<SNIP> 

Per fare alcuni calcoli sui dati, ho' Mi piace massaggiarlo in modo che ogni combinazione di data, identificatore, descrizione e posizione abbia una riga nella tabella con NA come valore1 e valore2. Conosco l'intervallo di date e tutti i potenziali valori per la posizione.

Sono nuovo sia per R che per data.table e la mia mente è fica a questo punto. Il risultato mi piacerebbe venire con per la tabella di esempio di cui sopra è:

date,identifier,description,location,value1,value2 
2014-03-01,1,foo,1,100,200 
2014-03-01,1,foo,2,200,300 
2014-04-01,1,foo,1,100,200 
2014-04-01,1,foo,2,100,200 
2014-05-01,1,foo,1,100,200 
2014-05-01,1,foo,2,100,200 
2014-03-01,2,bar,1,100,200 
2014-03-01,2,bar,2,NA,NA 
2014-04-01,2,bar,1,100,200 
2014-04-01,2,bar,2,NA,NA 
2014-05-01,2,bar,1,100,200 
2014-05-01,2,bar,2,NA,NA 
2014-03-01,3,baz,1,100,200 
2014-03-01,3,baz,2,200,300 
2014-04-01,3,baz,1,100,200 
2014-04-01,3,baz,2,100,200 
2014-05-01,3,baz,1,100,200 
2014-05-01,3,baz,2,100,200 
2014-03-01,4,quux,1,NA,NA 
2014-03-01,4,quux,2,NA,NA 
2014-04-01,4,quux,1,NA,NA 
2014-04-01,4,quux,2,NA,NA 
2014-05-01,4,quux,1,NA,NA 
2014-05-01,4,quux,2,100,200 

I dati nel database è sparsa in che un dato identificativo/descrizione/combinazione posizione potrebbe avere un qualsiasi numero di voci o nessuno tutto per ogni data. Voglio arrivare a un determinato intervallo di date (ad es., Dal 2014-03-01 al 2014-05-01) ogni identificatore/descrizione e posizione ha una riga nella tabella.

Questo sembra che ci sia un interessante trucco data.table da fare, ma sto blanking.

Modifica: l'ho fatto su una scala più piccola per un identificatore/descrizione unendomi in un altro datatable ma non sono sicuro di come farlo con la complessità aggiuntiva di più identificativi/descrizioni e posizioni.

Grazie mille per le vostre risposte.

Ecco uscita dput dei dati originali che possono essere facilmente copiato nella R:

structure(list(date = structure(c(1L, 1L, 2L, 2L, 3L, 3L, 1L, 2L, 3L, 1L, 1L, 2L, 2L, 3L, 3L, 3L), 
.Label = c("2014-03-01", "2014-04-01", "2014-05-01"), class = "factor"), 
identifier = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L),  
description = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 4L), 
.Label = c("bar", "baz", "foo", "quux"), class = "factor"), 
location = c(1L, 2L, 1L, 2L, 1L, 2L, 1L, 1L, 1L, 1L, 2L, 1L, 2L, 1L, 2L, 2L), 
value1 = c(100L, 200L, 100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L, 200L, 100L, 100L, 100L, 100L, 100L), 
value2 = c(200L, 300L, 200L, 200L, 200L, 200L, 200L, 200L, 200L, 200L, 300L, 200L, 200L, 200L, 200L, 200L)), 
.Names = c("date", "identifier", "description", "location", "value1", "value2"), 
row.names = c(NA, -16L), 
class = c("data.table", "data.frame")) 
+1

'rbind (DT0, DT0 [, (valore1 = NA_integer_, value2 = NA_integer _), da = (data, identificatore, descrizione , posizione)]) "si adatta alla descrizione verbale, ma l'output fornito altera solo le righe" bar ". – Frank

+0

Hai provato qualcosa come ... 'read.csv ('filename', sep = ',')' e che usare il formato data per la prima colonna ?? O forse ho una domanda missundertood ... –

+0

Se questa è la risposta giusta, questa domanda è quasi un dupe di http://stackoverflow.com/q/30109017/1191259 – Frank

risposta

4

Con l'aiuto di @akrun e @eddi, ecco il modo in cui idiomatica (?):

mycols = c("description","date","location") 
setkeyv(DT0,mycols) 
DT1 <- DT0[J(do.call(CJ,lapply(mycols,function(x)unique(get(x)))))] 
# alternately: DT1 <- DT0[DT0[,do.call(CJ,lapply(.SD,unique)),.SDcols=mycols]] 

La colonna identifier manca per le nuove righe, ma può essere riempito:..

setkey(DT1,description) 
DT1[unique(DT0[,c("description","identifier"),with=FALSE]),identifier:=i.identifier] 
+0

Questo è quello che mi è venuto in mente 'DT1 [DT0 [, c (3,1,4,2,5,6), con = FALSE], c (paste0 ('valore', 1: 2), 'identificatore'): = lista (i.value1, i.value2, i.identifier)] [, identificatore: = identificatore [! is.na (identificatore)] [1L], descrizione] [ordine (identificatore, data, descrizione)] ' – akrun

+0

La tua soluzione è decisamente migliore – akrun

+1

Sono un po 'confuso - stai cercando di generalizzare 'DT0 [CJ (unique (description), unique (date), unique (location))]', in modo da non dover scrivi di unique's o c'è ancora qualcos'altro che mi manca? – eddi

1

Se ho capito la domanda, giustamente - e utilizzando solo basare R, senza alcun data.table speciale:

# The fields for whose every permutation we require a row 
unique.fields <- c("date", "identifier", "description", "location") 
filler <- expand.grid(sapply(unique.fields, function(f) unique(foo[,f]))) 
merge(filler, foo, by=unique.fields, all.x=TRUE) 
+1

Il tuo 'expand.grid' fornisce 96 righe. Poiché l'identificatore e la descrizione sono 1-a-1 (baz è sempre 2, ecc.), Non si vuole prendere il loro prodotto incrociato. – Frank