Dear list,
I have the following problem. Could anyone help?
x
<- as.factor(letters[1:5])
x <- x[-4]
levels(x)
The levels(x) still gives you 5 rather than 4 levels. Of course, I can do
levels(as.factor(as.character(x)) to get rid of the non-existing factor
level. But, I think there must be a simpler way.
[WNV] it’s
not clear that there is, or even should be, a simpler way. It depends
entirely on what you want to happen when you alter the factor by removing a
component.
In principle a
factor is used to define a classification. There are two parts to it that
in principle operate independently, namely the names of the classes into which
the factor can define membership (i.e. the factor levels) and the membership of
each candidate for which the factor does its job. It’s not clear
that if you remove one of the candidates, and by so doing make the membership
of a particular group empty, that the levels should change to exclude it.
Even the
solution you propose will not completely do what you want to happen, anyway,
since it will re-order the levels so that their names are in sorted
order. If the original names were not in sorted order, you would have altered
that as well.
I take it what
you would like to happen is that when you make one or more of the levels of a
factor empty the new factor has a reduces levels attribute.
Here is a
function that will do this, but I emphasise that it is quite arbitrary:
fixFactor
<- function(x) {
newLevels <- levels(x)[table(x) > 0]
factor(as.character(x), levels = newLevels)
}
Here is a brief
demo
> x
[1] a b
c d e a b c d e
> table(x)
# levels in reverse alpha order
e d c b
a
2 2 2 2
2
> y <-
x[-c(1,6)]
> y # note that the printout implicitly warns levels missing
[1] b c d e b
c d e
Levels:
[1]
"e" "d" "c" "b" "a"
> table(y)
e d c b
a
2 2 2 2
0
> y <-
fixFactor(y)
> table(y)
e d c b
2 2 2 2
>
Thanks
Yiwu