2015-05-13 17 views
5

Ich habe einen data.table in R, die aus einer Datenbank abgerufen wurde, das wie folgt aussieht:Fill fehlenden Zeilen mit 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> 

Um einige Berechnungen auf den Daten zu tun, ich d möchte es so massieren, dass jede Kombination aus Datum, Bezeichner, Beschreibung und Ort eine Zeile in der Tabelle mit NA als Wert1 und Wert2 aufweist. Ich kenne den Datumsbereich und alle möglichen Werte für den Standort.

Ich bin neu sowohl R und data.table und meine Meinung ist Brei an diesem Punkt. Das Ergebnis Ich mag würde mit dem obigen Probentisch kommen ist:

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 

Die Daten in der Datenbank in dem spärlichen eine gegebene Kennung/Beschreibung/Standort Kombination beliebig viele Einträge oder keine haben könnte bei alles für jedes Datum. Ich möchte für einen bestimmten Zeitraum (z. B. 2014-03-01 bis 2014-05-01) zu jeder Kennung/Beschreibung und Ort hat eine Zeile in der Tabelle.

Dies scheint etwas zu sein, es wäre ein interessanter data.table Trick zu tun, aber ich blende.

Bearbeiten: Ich habe dies in einem kleineren Maßstab für eine Kennung/Beschreibung durch Zusammenführen in einer anderen Datentabelle, aber ich bin mir nicht sicher, wie dies mit der zusätzlichen Komplexität von mehreren Bezeichnern/Beschreibungen und Standorten zu tun.

Vielen Dank für Ihre Antworten. Hier

ist dput Ausgabe der Originaldaten, die leicht in R kopiert werden können:

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 [, (Wert1 = NA_integer_, Wert2 = NA_integer _), durch = (Datum, Bezeichner, Beschreibung , location)]) passt zu Ihrer verbalen Beschreibung, aber Ihre gegebene Ausgabe ändert nur 'bar' Zeilen. – Frank

+0

Haben Sie versucht, etwas wie ... 'read.csv ('Dateiname', sep = ',')' und dann mit dem Datumsformat für die erste Spalte ?? Oder vielleicht ich missunderdood Frage ... –

+0

Wenn das die richtige Antwort ist, ist diese Frage fast ein Betrüger von http://stackoverflow.com/q/30109017/1191259 – Frank

Antwort

4

Mit Hilfe von @akrun und @eddi, hier ist der idiomatische Weg (?):

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]] 

Die identifier Spalte wird für die neuen Zeilen fehlt, kann aber gefüllt werden:..

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

Das ist, was ich mit 'DT1 [DT0 [, c (3,1,4,2,5,6), mit = FALSCH], c (paste0 ('Wert', 1: 2), 'Bezeichner')): = liste (i.value1, i.value2, i.identifier)] [, identifier: = identifier [! is.na (identifier)] [1L], description] [order (identifier, date, description)] ' – akrun

+0

Ihre Lösung ist viel besser – akrun

+1

Ich bin ein wenig verwirrt - versuchen Sie zu verallgemeinern 'DT0 [CJ (einzigartig (Beschreibung), einzigartig (Datum), einzigartig (Ort))], so dass Sie nicht müssen schreibe Unique's oder gibt es noch etwas anderes, dass ich vermisse? – eddi

1

Wenn ich die Frage richtig zu verstehen - und mit der Basis nur R, keine spezielle data.table:

# 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

Ihr 'expand.grid' gibt 96 Zeilen. Da Bezeichner und Beschreibung 1 zu 1 sind (baz ist immer 2 usw.), möchten Sie ihr Cross-Produkt nicht verwenden. – Frank