# [R] recursive relevel

baptiste auguie ba208 at exeter.ac.uk
Fri Jan 9 15:39:48 CET 2009

```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
>> 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
>> 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