Ich habe einen langen Vektor der Klasse Faktor, der NA
Werte enthält.Effizient führen neue Ebene auf einem Faktor Vektor
# simple example
x <- factor(c(NA,'A','B','C',NA), levels=c('A','B','C'))
Zum Zwecke der Modellierung wünsche ich diese NA
Werte mit einem Faktor neuen Ebene ersetzen (beispielsweise ‚Unknown‘), und diese Pegel als Referenzpegel gesetzt.
Da das Ersatzniveau ist nicht eine bestehende Ebene, ist ein einfacher Austausch nicht:
# this won't work, since the replacement value is not an existing level of the factor
x[is.na(x)] <- '?'
x # returns: [1] <NA> A B C <NA> -- the NAs remain
# this doesn't work either:
replace(x, NA,'?')
ich mit ein paar Lösungen kam, aber beide sind so eine Art hässlich und überraschend langsam.
f1 <- function(x, uRep='?'){
# convert to character, replace NAs with Unknown, and convert back to factor
stopifnot(is.factor(x))
newLevels <- c(uRep,levels(x))
x <- as.character(x)
x[is.na(x)] <- uRep
factor(x, levels=newLevels)
}
f2 <- function(x, uRep='?'){
# add new level for Unknown, replace NAs with Unknown, and make Unknown first level
stopifnot(is.factor(x))
levels(x) <- c(levels(x),uRep)
x[is.na(x)] <- uRep
relevel(x, ref=uRep)
}
f3 <- function(x, uRep='?'){ # thanks to @HongOoi
y <- addNA(x)
levels(y)[length(levels(y))]<-uRep
relevel(y, ref=uRep)
}
#test
f1(x) # works
f2(x) # works
f3(x) # works
Lösung # 2 ist die Bearbeitung nur die (relativ kleine) Menge von Ebenen, plus eine arithmetische op nivellieren. Ich hätte erwartet, dass das schneller als # 1 ist, was zum Charakter und zurück zum Faktor führt.
Allerdings ist # 2 doppelt so langsam auf einem Benchmark-Vektor von 10K Elementen mit 10 Ebenen und 10% NA.
x <- sample(factor(c(LETTERS[1:10],NA),levels=LETTERS[1:10]),10000,replace=TRUE)
library(microbenchmark)
microbenchmark(f1(x),f2(x),f3(x),times=500L)
# Unit: microseconds
# expr min lq mean median uq max neval
# f1(x) 271.981 278.1825 322.4701 313.0360 360.7175 609.393 500
# f2(x) 651.728 703.2595 768.6756 747.9480 825.7800 1517.707 500
# f3(x) 808.246 883.2980 966.2374 927.5585 1061.1975 1779.424 500
Lösung # 3, mein Wrapper für den eingebauten in addNA
(unten in der Antwort erwähnt) als entweder langsamer war. addNA
führt einige Extra-Prüfungen für NA
Werte durch und setzt die neue Ebene als letzte (die ich wieder aufheben muss) und benannt NA (die dann Umbenennung nach Index erfordert, da NA schwer zugänglich ist - relevel(addNA(x), ref=NA_character_))
funktioniert nicht) .
Gibt es eine effizientere Möglichkeit, dies zu schreiben, oder werde ich nur abgespritzt?
einfach tun 'addNA' nicht die NA Ebene als Referenzpegel ist festgelegt, noch mit den gewünschten Niveau Namen ersetzt. Dies funktioniert nicht: 'relevel (addNA (x), ref = NA_character_)' – C8H10N4O2