recursive relevel
On 9 Jan 2009, at 15:26, Dimitris Rizopoulos wrote:
I think that you can still use to core of stats:::relevel.factor; the
only thing that needs to be changed is the controls for bad values of
the 'ref' argument, i.e.,
relevelNew <- function (x, ref, ...) {
lev <- levels(x)
if (is.character(ref))
ref <- match(ref, lev)
if (any(is.na(ref)))
stop("'ref' must be an existing level")
nlev <- length(lev)
if (any(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])])
}
ff <- factor(c("a", "b", "c", "d"))
ff
relevelNew(ff, "c")
relevelNew(ff, c("c", "d"))
I hope it helps.
Best,
Dimitris
Very good point! I knew I was missing something obvious, but I was wrongly assuming that the changes needed were more drastic. I'm now wondering why this wasn't implemented in relevel() in the first place. Perhaps such a small modification could be useful, at least in the documentation? Thanks, baptiste
baptiste auguie wrote:
Dear list,
I'm having second thoughts after solving a very trivial problem: I
want
to extend the relevel() function to reorder an arbitrary number of
levels of a factor in one go. I could not find a trivial way of using
the code obtained by getS3method("relevel","factor"). Instead, I
thought
of solving the problem in a recursive manner (possibly after reading
Paul Graham essays on Lisp too recently). Here is my attempt :
order.factor <- function (x, ref)
{
last.index <- length(ref) # convenience for matlab's end keyword
if(last.index == 1) return(relevel(x, ref)) # end case, normal
case of relevel
my.new.list <- list(x=relevel(x, ref[last.index]), # creating a
list with updated parameters,
# going
through the list in reverse order
ref=ref[-last.index]) # chop the vector
from its last level
return(do.call(order.factor, my.new.list)) # recursive call
}
ff <- factor(c("a", "b", "c", "d"))
ff
relevel(ff, levels(ff)[1])
relevel(ff, levels(ff)[2]) # that's the usual case: you want to
put a
level first
order.factor(x=ff, ref=c("a", "b"))
order.factor(x=ff, ref=c("c"))
order.factor(x=ff, ref=c("c", "d")) # that's my wish: put c and d in
that order as the first two levels
I'm hoping this can be improved in several aspects: - there is probably already a better function I missed or overlooked (I'd still be curious about the following points, though) - after reading a few threads, it appears that some recursive functions are fragile in some sense, and I'm not sure what this means in practice. (Should I use Recall, somehow?) - it's probably quite slow for large data.frames - I could not think of a good name, this one might clash with some S3 method perhaps? - any other thoughts welcome! Best wishes, Baptiste
_____________________________ Baptiste Augui? School of Physics University of Exeter Stocker Road, Exeter, Devon, EX4 4QL, UK Phone: +44 1392 264187 http://newton.ex.ac.uk/research/emag ______________________________________________ R-help at 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.
-- Dimitris Rizopoulos Assistant Professor Department of Biostatistics Erasmus Medical Center Address: PO Box 2040, 3000 CA Rotterdam, the Netherlands Tel: +31/(0)10/7043478 Fax: +31/(0)10/7043014
_____________________________ Baptiste Augui? School of Physics University of Exeter Stocker Road, Exeter, Devon, EX4 4QL, UK Phone: +44 1392 264187 http://newton.ex.ac.uk/research/emag