Commenting on this, is there a strong argument against modifying relevel() to reorder more than one level at a time?

I started a topic a while back ("recursive relevel", https://stat.ethz.ch/pipermail/r-help/2009-January/184397.html) and I've happily used the proposed change since then by overloading stats:::relevel.factor.

I'm sure there should be additional checking (for which I'm not versed enough in programming to propose a real patch) but the enhanced functionality seems very desirable (especially for plotting).

Best regards,

baptiste




Peter Dalgaard wrote:
Mark Difford wrote:
Hi Mao,

I am confused. And, I want to know how to assign a wanted order to factor levels, intentionally?
You want ?relevel. Although the documentation leads one to think that it can
only be used to set a reference level, with the other levels being moved
down, presently it can in fact be used to set any order you wish. For a
factor with just a few levels you could simply use an index into the default
order.

##
new_d <- d
c(5,1,6:10,2:4)
new_d$population <- relevel(d$population,
levels(d$population)[c(5,1,6:10,2:4)])

Ignore the warning. Note that relevel can also be used "on-the-fly," so
without permanently changing level-order.

Now that's a dangerous strategy! You're relying on undocumented
behaviour and ignoring a warning message to boot. If someone implements
a check that ref is a scalar as assumed, you're shot.

Better to have a look at why stats:::relevel.factor currently works and
use the same mechanism:

    lev <- levels(x)
    if (is.character(ref))
        ref <- match(ref, lev)
    if (is.na(ref))
        stop("'ref' must be an existing level")
    nlev <- length(lev)
    if (ref < 1 || ref > nlev)
        stop(gettextf("ref = %d must be in 1:%d", ref, nlev),
            domain = NA)
    factor(x, levels = lev[c(ref, seq_along(lev)[-ref])])

and if you assume an integer reordering in ref, this reduces to

    lev <- levels(x)
    factor(x, levels = lev[ref])

and if ref is a character vector, plain

    factor(x, levels=ref)

should do.

(Or, you can go "full monty" and retain all the checks an balances, just
cure the warning using

if (any(is.na(ref))
        stop("'ref' must contain existing levels")
...
if (any(ref < 1 | ref > nlev))

Maybe also check !any(duplicated(ref)) for good measure
)



______________________________________________
R-help@r-project.org mailing list
https://stat.ethz.ch/mailman/listinfo/r-help
PLEASE do read the posting guide http://www.R-project.org/posting-guide.html
and provide commented, minimal, self-contained, reproducible code.

Reply via email to