Όταν μετατρέπω έναν παράγοντα σε αριθμητικό ή ακέραιο αριθμό, λαμβάνω τους υποκείμενους κωδικούς επιπέδων, όχι τις τιμές ως αριθμούς.
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
Πρέπει να καταφύγω στην "επικόλληση" για να πάρω τις πραγματικές τιμές:
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
Υπάρχει καλύτερος τρόπος να μετατρέψω έναν παράγοντα σε αριθμητικό;
Δείτε την ενότητα Προειδοποίηση του ?factor
:
Ειδικότερα, το as.numeric
εφαρμόζεται στο
έναν παράγοντα δεν έχει νόημα, και μπορεί να συμβεί με σιωπηρό εξαναγκασμό. Στο μετατρέψουμε έναν παράγοντα
f
σε περίπου τον αρχικό αριθμητικό του τιμές, ηas.numeric(levels(f))[f]
είναι συνιστάται και ελαφρώς περισσότερο αποδοτικότερο από τοas.numeric(as.character(f))
.
Οι Συχνές Ερωτήσεις για την R έχουν παρόμοιες συμβουλές.
Γιατί το as.numeric(levels(f))[f]
είναι πιο αποτελεσματικό από το as.numeric(as.character(f))
;
Το as.numeric(as.character(f))
είναι ουσιαστικά as.numeric(levels(f)[f])
, οπότε εκτελείτε τη μετατροπή σε αριθμητικό στις τιμές length(x)
και όχι στις τιμές nlevels(x)
. Η διαφορά ταχύτητας θα είναι πιο εμφανής για μεγάλα διανύσματα με λίγα επίπεδα. Εάν οι τιμές είναι ως επί το πλείστον μοναδικές, δεν θα υπάρχει μεγάλη διαφορά στην ταχύτητα. Όπως και να κάνετε τη μετατροπή, αυτή η λειτουργία είναι απίθανο να είναι το σημείο συμφόρησης στον κώδικά σας, οπότε μην ανησυχείτε πολύ γι' αυτό.
Κάποιοι χρονισμοί
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 διαθέτει μια σειρά από (μη τεκμηριωμένες) συναρτήσεις ευκολίας για τη μετατροπή παραγόντων:
as.data.frame.factor
as.Date.factor
as.list.factor
as.vector.factor
Αλλά, ενοχλητικά, δεν υπάρχει τίποτα για να χειριστεί τη μετατροπή παράγοντας -> αριθμητική. Ως επέκταση της απάντησης του Joshua Ulrich's, θα πρότεινα να ξεπεράσετε αυτή την παράλειψη με τον ορισμό της δικής σας ιδιότυπης συνάρτησης:
as.numeric.factor <- function(x) {as.numeric(levels(x))[x]}
την οποία μπορείτε να αποθηκεύσετε στην αρχή του σεναρίου σας, ή ακόμα καλύτερα στο αρχείο .Rprofile
.
Είναι δυνατή μόνο στην περίπτωση που οι ετικέτες των παραγόντων αντιστοιχούν στις αρχικές τιμές. Θα το εξηγήσω με ένα παράδειγμα.
Ας υποθέσουμε ότι τα δεδομένα είναι το διάνυσμα x
:
x <- c(20, 10, 30, 20, 10, 40, 10, 40)
Τώρα θα δημιουργήσω έναν παράγοντα με τέσσερις ετικέτες:
f <- factor(x, levels = c(10, 20, 30, 40), labels = c("A", "B", "C", "D"))
x
είναι τύπου double, το f
είναι τύπου integer. Αυτή είναι η πρώτη αναπόφευκτη απώλεια πληροφορίας. Οι συντελεστές αποθηκεύονται πάντα ως ακέραιοι αριθμοί.> typeof(x)
[1] "double"
> typeof(f)
[1] "integer"
f
διαθέσιμο. Μπορούμε να δούμε ότι το f
κρατάει μόνο τις ακέραιες τιμές 1, 2, 3, 4 και δύο χαρακτηριστικά - τη λίστα των ετικετών ("A", "B", "C", "D") και το χαρακτηριστικό της κλάσης "factor". Τίποτα περισσότερο.> 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"
Για να επιστρέψουμε στις αρχικές τιμές πρέπει να γνωρίζουμε τις τιμές των επιπέδων που χρησιμοποιήθηκαν για τη δημιουργία του παράγοντα. Σε αυτή την περίπτωση c(10, 20, 30, 40)
. Εάν γνωρίζουμε τα αρχικά επίπεδα (με τη σωστή σειρά), μπορούμε να επιστρέψουμε στις αρχικές τιμές.
> orig_levels <- c(10, 20, 30, 40)
> x1 <- orig_levels[f]
> all.equal(x, x1)
[1] TRUE
Και αυτό θα λειτουργήσει μόνο στην περίπτωση που έχουν οριστεί ετικέτες για όλες τις πιθανές τιμές στα αρχικά δεδομένα.
Επομένως, αν θα χρειαστείτε τις αρχικές τιμές, θα πρέπει να τις κρατήσετε. Διαφορετικά, υπάρχει μεγάλη πιθανότητα να μην είναι δυνατόν να επιστρέψετε σε αυτές μόνο από έναν παράγοντα.