Wenn ich einen Faktor in einen numerischen oder ganzzahligen Wert umwandle, erhalte ich die zugrunde liegenden Ebenencodes und nicht die Werte als Zahlen.
f <- factor(sample(runif(5), 20, replace = TRUE))
## [1] 0.0248644019011408 0.0248644019011408 0.179684827337041
## [4] 0.0284090070053935 0.363644931698218 0.363644931698218
## [7] 0.179684827337041 0.249704354675487 0.249704354675487
## [10] 0.0248644019011408 0.249704354675487 0.0284090070053935
## [13] 0.179684827337041 0.0248644019011408 0.179684827337041
## [16] 0.363644931698218 0.249704354675487 0.363644931698218
## [19] 0.179684827337041 0.0284090070053935
## 5 Levels: 0.0248644019011408 0.0284090070053935 ... 0.363644931698218
as.numeric(f)
## [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2
as.integer(f)
## [1] 1 1 3 2 5 5 3 4 4 1 4 2 3 1 3 5 4 5 3 2
Ich muss auf "Einfügen" zurückgreifen, um die echten Werte zu erhalten:
as.numeric(paste(f))
## [1] 0.02486440 0.02486440 0.17968483 0.02840901 0.36364493 0.36364493
## [7] 0.17968483 0.24970435 0.24970435 0.02486440 0.24970435 0.02840901
## [13] 0.17968483 0.02486440 0.17968483 0.36364493 0.24970435 0.36364493
## [19] 0.17968483 0.02840901
Gibt es eine bessere Möglichkeit, einen Faktor in einen numerischen Wert umzuwandeln?
Siehe den Abschnitt Warnung in ?factor
:
Insbesondere ist as.numeric
angewendet auf
einen Faktor ist bedeutungslos, und kann durch implizite Erzwingung geschehen. Um einen Faktor
f
zu transformieren ungefähr seine ursprünglichen numerischen Werte zu transformieren, ist "as.numeric(levels(f))[f]empfohlen und etwas effizienter effizienter als "as.numeric(as.character(f))
.
Die FAQ zu R enthält ähnliche Ratschläge.
Warum ist as.numeric(levels(f))[f]
effizienter als as.numeric(as.character(f))
?
as.numeric(as.character(f))ist im Grunde genommen as.numeric(levels(f)[f])
, d.h. Sie führen die Konvertierung in numerische Werte für length(x)
-Werte und nicht für nlevels(x)
-Werte durch. Der Geschwindigkeitsunterschied wird bei langen Vektoren mit wenigen Ebenen am deutlichsten. Wenn die Werte größtenteils eindeutig sind, gibt es keinen großen Geschwindigkeitsunterschied. Wie auch immer Sie die Konvertierung durchführen, es ist unwahrscheinlich, dass diese Operation der Engpass in Ihrem Code ist, also machen Sie sich nicht zu viele Gedanken darüber.
Einige Zeitangaben
library(microbenchmark)
microbenchmark(
as.numeric(levels(f))[f],
as.numeric(levels(f)[f]),
as.numeric(as.character(f)),
paste0(x),
paste(x),
times = 1e5
)
## Unit: microseconds
## expr min lq mean median uq max neval
## as.numeric(levels(f))[f] 3.982 5.120 6.088624 5.405 5.974 1981.418 1e+05
## as.numeric(levels(f)[f]) 5.973 7.111 8.352032 7.396 8.250 4256.380 1e+05
## as.numeric(as.character(f)) 6.827 8.249 9.628264 8.534 9.671 1983.694 1e+05
## paste0(x) 7.964 9.387 11.026351 9.956 10.810 2911.257 1e+05
## paste(x) 7.965 9.387 11.127308 9.956 11.093 2419.458 1e+05
R verfügt über eine Reihe von (undokumentierten) Komfortfunktionen zur Umrechnung von Faktoren:
as.character.factor
as.data.frame.factor
as.Datum.Faktor
as.list.factor
as.vector.factor
Aber ärgerlicherweise gibt es nichts, um die Faktor -> numerische Konvertierung zu behandeln. Als Erweiterung der Antwort von Joshua Ulrich würde ich vorschlagen, diese Lücke durch die Definition einer eigenen idiomatischen Funktion zu schließen:
as.numeric.factor <- function(x) {as.numeric(levels(x))[x]}
die Sie am Anfang Ihres Skripts oder noch besser in Ihrer .Rprofile
Datei speichern können.
Dies ist nur möglich, wenn die Faktorbezeichnungen mit den ursprünglichen Werten übereinstimmen. Ich werde es anhand eines Beispiels erklären.
Angenommen, die Daten sind der Vektor "x":
x <- c(20, 10, 30, 20, 10, 40, 10, 40)
Jetzt werde ich einen Faktor mit vier Bezeichnungen erstellen:
f <- factor(x, levels = c(10, 20, 30, 40), labels = c("A", "B", "C", "D"))
x
ist vom Typ double, f
ist vom Typ integer. Dies ist der erste unvermeidliche Informationsverlust. Faktoren werden immer als ganze Zahlen gespeichert.> typeof(x)
[1] "double"
> typeof(f)
[1] "integer"
> str(f)
Factor w/ 4 levels "A","B","C","D": 2 1 3 2 1 4 1 4
> attributes(f)
$levels
[1] "A" "B" "C" "D"
$class
[1] "factor"
Um zu den ursprünglichen Werten zurückzukehren, müssen wir die Werte der bei der Erstellung des Faktors verwendeten Ebenen kennen. In diesem Fall c(10, 20, 30, 40)
. Wenn wir die ursprünglichen Ebenen (in der richtigen Reihenfolge) kennen, können wir zu den ursprünglichen Werten zurückkehren.
> orig_levels <- c(10, 20, 30, 40)
> x1 <- orig_levels[f]
> all.equal(x, x1)
[1] TRUE
Und das funktioniert nur, wenn für alle möglichen Werte in den Originaldaten Bezeichnungen definiert wurden.
Wenn Sie also die Originalwerte benötigen, müssen Sie sie aufbewahren. Andernfalls besteht eine hohe Wahrscheinlichkeit, dass man nur über einen Faktor auf sie zurückgreifen kann.