Reputation: 5657
I'm returning to R after some time, and the following has me stumped:
I'd like to build a list of the positions factor values have in the facor levels list. Example:
> data = c("a", "b", "a","a","c")
> fdata = factor(data)
> fdata
[1] a b a a c
Levels: a b c
> fdata$lvl_idx <- ????
Such that:
> fdata$lvl_idx
[1] 1 2 1 1 3
Appreciate any hints or tips.
Upvotes: 12
Views: 12783
Reputation: 5269
The solution provided years ago by Matthew Lundberg is not robust. It could be that the as.integer()
function was defined for a specific S3 type of factors. Imagine someone would create a new factor class to keep operators like >=
.
as.myfactor <- function(x, ...) {
structure(as.factor(x), class = c("myfactor", "factor"))
}
# and that someone would create an S3 method for integers - it should
# only remove the operators, which makes sense...
as.integer.myfactor <- function(x, ...) {
as.integer(gsub("(<|=|>)+", "", as.character(x)))
}
Now this is not working anymore, - it just removes operators:
f <- as.myfactor(">=2")
as.integer(f)
#> [1] 2
But this is robust with any factor you want to know the index of the level of, using which()
:
f <- factor(2:4)
which(levels(f) == 2)
#> [1] 1
Upvotes: 6
Reputation: 42689
If you convert a factor to integer, you get the position in the levels:
as.integer(fdata)
## [1] 1 2 1 1 3
In certain situations, this is counter-intuitive:
f <- factor(2:4)
f
## [1] 2 3 4
## Levels: 2 3 4
as.integer(f)
## [1] 1 2 3
Also if you silently coerce to integer, for example by using a factor as a vector index:
LETTERS[2:4]
## [1] "B" "C" "D"
LETTERS[f]
## [1] "A" "B" "C"
Converting to character
before converting to integer
gives the expected values. See ?factor
for details.
Upvotes: 14