RE: [R] A suggestion to improve ifelse behaviour with vector yes/noarguments

From: Mäkinen Jussi <Jussi.Makinen_at_valtiokonttori.fi>
Date: Wed 01 Jun 2005 - 16:47:43 EST

> Thomas Lumley wrote:
> > On Tue, 31 May 2005, Duncan Murdoch wrote:
> >
> >
> >>Mäkinen Jussi wrote:
> >>
> >>>Dear All,
> >>>
> >>>I luckily found the following feature (or problem) when tried to
> >>>apply
> >>>ifelse-function to an ordered data.
> >>>
> >>>
> >>>
> >>>>test <- c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE) ifelse(test,
> >>>>0, 1:4)
> >>>
> >>>[1] 0 0 0 4 1 2 3
> >>>
> >
> > <snippage>
> >
> >>As Dimitris said, this is just recycling. I think getting rid of
> >>recycling
> >>on vectors with length greater than 1 would have been a good decision in S
> >>about 15 years ago, but it's too late now.
> >
> >
> > It wouldn't help the original poster, though. I agree that
> > 0,0,0,4,1,2,3
> > is a slightly weird result, but I can't think of any reasonable model for
> > the behaviour of ifelse() that would give any other result except an error
> > message. [or 0,NA,NA,4,NA,NA,NA, I suppose].
>
> I would vote for the error message. I can't think of a single example
> where a vector of length 7 is needed, and a vector of length 4 is
> recycled to give it, that *doesn't* give a slightly weird result.
>
> Maybe this is something that should have been changed in R 2.0.0; we
> squandered that change from 1.x.x to 2.x.x.
>
> Duncan Murdoch

Hello,

I'm happy with the modified ifelse:

ifelse.o <- function (test, yes, no)
{

    storage.mode(test) <- "logical"
    ans <- test
    nas <- is.na(test)
    if (any(test[!nas]))

        ans[test & !nas] <- rep(yes, length.out = length(ans))[test & 
            !nas]
    if (any(!test[!nas])) 
		### Changed
        ans[!test & !nas] <- rep(no, length.out = length(ans[!test & !nas]))
    ans[nas] <- NA
    ans
}

giving me:

> test <- c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE)
> ifelse.o(test, 0, 1:4)
 [1] 0 0 0 1 2 3 4

and

> test <- c(FALSE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)
> ifelse.o(test, 0, 1:4)

 [1] 1 2 0 0 0 3 4 1 2 3 4

comparing to:

> ifelse(test, 0, 1:4)
 [1] 1 2 0 0 0 2 3 4 1 2 3

So in 'ifelse.o' the recycling starts from the first element of the 'no' -argument and continues the cycling in a logical way (IMHO). That is something I expected 'ifelse' would do.

Thank you for your comments,

Jussi Mäkinen



R-help@stat.math.ethz.ch mailing list
https://stat.ethz.ch/mailman/listinfo/r-help PLEASE do read the posting guide! http://www.R-project.org/posting-guide.html Received on Wed Jun 01 16:52:04 2005

This archive was generated by hypermail 2.1.8 : Fri 03 Mar 2006 - 03:32:20 EST