[R] recursive relevel

Dimitris Rizopoulos d.rizopoulos at erasmusmc.nl
Fri Jan 9 15:26:00 CET 2009


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


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




More information about the R-help mailing list