Wenn man in fehlenden Werten einer Variablen bei früheren/posterior nicht NA Beobachtung innerhalb einer Gruppe auf Basis füllen möge, der data.table Befehlin fehlenden Werten durch Gruppe in data.table
setkey(DT,id,date)
DT[, value_filled_in := DT[!is.na(value), list(id, date, value)][DT[, list(id, date)], value, roll = TRUE]]
welche ist ziemlich komplex. Es ist schade, da roll
ist eine sehr schnelle und leistungsfähige Option (va im Vergleich mit einer Funktion wie zoo::na.locf
innerhalb jeder Gruppe der Anwendung)
ich eine Komfortfunktion in fehlenden Werten schreibe
fill_na <- function(x , by = NULL, roll =TRUE , rollends= if (roll=="nearest") c(TRUE,TRUE)
else if (roll>=0) c(FALSE,TRUE)
else c(TRUE,FALSE)){
id <- seq_along(x)
if (is.null(by)){
DT <- data.table("x" = x, "id" = id, key = "id")
return(DT[!is.na(x)][DT[, list(id)], x, roll = roll, rollends = rollends, allow.cartesian = TRUE])
} else{
DT <- data.table("x" = x, "by" = by, "id" = id, key = c("by", "id"))
return(DT[!is.na(x)][DT[, list(by, id)], x, roll = roll, rollends = rollends, allow.cartesian = TRUE])
}
}
Und dann zu füllen schreiben
setkey(DT,id, date)
DT[, value_filled_in := fill_na(value, by = id)]
Das ist nicht wirklich befriedigend ist, da man
setkey(DT,id, date)
DT[, value_filled_in := fill_na(value), by = id]
schreiben möchten
Dies dauert jedoch sehr viel Zeit. Und für den Endbenutzer ist es umständlich zu erfahren, dass fill_na
mit der Option by
aufgerufen werden sollte und nicht mit data.table
by
verwendet werden sollte. Gibt es dafür eine elegante Lösung?
Einige Geschwindigkeitstest
N <- 2e6
set.seed(1)
DT <- data.table(
date = sample(10, N, TRUE),
id = sample(1e5, N, TRUE),
value = sample(c(NA,1:5), N, TRUE),
value2 = sample(c(NA,1:5), N, TRUE)
)
setkey(DT,id,date)
DT<- unique(DT)
system.time(DT[, filled0 := DT[!is.na(value), list(id, date, value)][DT[, list(id, date)], value, roll = TRUE]])
#> user system elapsed
#> 0.086 0.006 0.105
system.time(DT[, filled1 := zoo::na.locf.default(value, na.rm = FALSE), by = id])
#> user system elapsed
#> 5.235 0.016 5.274
# (lower speed and no built in option like roll=integer or roll=nearest, rollend, etc)
system.time(DT[, filled2 := fill_na(value, by = id)])
#> user system elapsed
#> 0.194 0.019 0.221
system.time(DT[, filled3 := fill_na(value), by = id])
#> user system elapsed
#> 237.256 0.913 238.405
Warum ich na.locf.default
einfach nicht benutzen? Obwohl der Geschwindigkeitsunterschied nicht wirklich wichtig ist, tritt das gleiche Problem für andere Arten von data.table-Befehlen auf (solche, die auf einer Zusammenführung durch die Variable in "by" beruhen) - es ist eine Schande, sie systematisch zu ignorieren, um einen zu erhalten leichtere Syntax Ich mag auch wirklich alle Rollenoptionen.
Wie funktioniert die 'na.locf' Lösung zu dieser Lösung in Bezug auf Geschwindigkeit vergleichen? – GSee
Ist das ganze Ding (a la 'dplyr :: mutate') nicht eine Option? – shadowtalker
Es wäre hilfreich, wenn Sie Code zur Verfügung stellen würden, um [Beispieldaten.table] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproductible-example) zu erstellen Verwenden Sie, um unsere Ergebnisse zu überprüfen und beim Benchmarking zu helfen. – GSee