[R] How to avoid ifelse statement converting factor to character

Craig P. Pyrame crappyr at gmail.com
Thu Jun 25 02:27:25 CEST 2009


Dear Stavros,

What you discuss below is somewhat scary to me as an R newbie.  Is this 
just an incident, a bug perhaps, or rather the way things typically go 
in R, as your "Welcome to R!" seems to suggest?  I have just started to 
learn R, and my initial euphoria of the "I can do anything with it!" 
sort is gradually turning into an "I can't get why it doesn't work" and 
"I can't get how to make this work" depression.  I would be happy to 
blame this on my incompetence and incapability, but would also like to 
hear if it is not R itself that causes me to fail.

Best regards,
Craig


Stavros Macrakis wrote:
> On Wed, Jun 24, 2009 at 12:34 PM, Mark Na<mtb954 at gmail.com> wrote:
>   
>> The problem is that after running the ifelse statement, data$SOCIAL_STATUS
>> is converted from a factor to a character.
>> Is there some way I can avoid this conversion?
>>     
>
> I'm afraid that ifelse has very bizarre semantics when the yes and no
> arguments don't have the same, atomic vector, type.
>
> The quick workaround for the bizarre semantics (though it can have a
> significant efficiency cost) is this:
>
>        unlist( ifelse ( condition, as.list( yes ), as.list( no ) ) )
>
> (This isn't perfect, either, but...)
>
> Take a look at the man page for details and the warning:
>
>      The mode of the result may depend on the value of 'test', and the
>      class attribute of the result is taken from 'test' and may be
>      inappropriate for the values selected from 'yes' and 'no'.
>
> Some consequences of the definition of ifelse are:
>
> Even if the classes of the yes and no arguments are identical, the
> result does not necessarily have that class:
>
>     ifelse(TRUE,as.raw(4),as.raw(5)) => error
>
>     ifelse(TRUE,factor('x'),factor('x')) => 1      (integer)
>
>     dates <- as.POSIXct(c('1990-1-1','2000-1-1'))
>     ifelse(c(TRUE,FALSE),dates,dates)  =>  631170000 946702800  (double)
>
>     ifelse(c(TRUE,FALSE),factor(c('x','y')),factor(c('y','x'))) => 1 1
>
> If they have different classes, things get stranger:
>
>     ifelse(c(TRUE,FALSE),c("a","b"),factor(c("c","d")))  =>  "a" "2"
>
>     ifelse(c(TRUE,FALSE),list(1,2),as.raw(4))
>     [[1]]
>     [1] 1
>
>     [[2]]
>     [1] 04
>
> Result is order-dependent:
>
>     ifelse(c(TRUE,FALSE),as.raw(4),list(1,2))
>     Error in ans[test & !nas] <- rep(yes, length.out = length(ans))[test &  :
>     incompatible types (from raw to logical) in subassignment type fix
>
> Welcome to R!
>




More information about the R-help mailing list