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

Craig P. Pyrame crappyr at gmail.com
Sat Jun 27 01:03:13 CEST 2009


Dear Peter,

Thank you for the explanations. Some further questions are inlined below.

Best regards,
Craig


Peter Dalgaard wrote:
> Craig P. Pyrame wrote:
>> Stavros Macrakis wrote:
>>> It gives me a headache, too! I think you'll have to wait for a more
>>> expert user than me to supply explanations of these behaviors and
>>> their rationales. 
>>
>> Thanks, Stavros. I hope someone with expertise will shed more light 
>> on this, and in the meantime I'll try to learn more from the manuals.
>
> Well first, you (and others) should shake any bees relating to "raw" 
> objects out of your bonnet. The raw type should be viewed as an add-on 
> enabling access to low-level data structures, not as a fundamental 
> data type in R. The original data modes are logical, numeric, 
> character, with "upwards" coercion rules (and some further twiddles 
> for storage modes of numerics).

I think I've seen examples in the list's archives where downwards 
coercion rules were used, but I am not sure.


>
> One particular aspect is that in the original system, logical works as 
> a "wild card" type that can be coerced to all the others (hence NA has 
> mode "logical", which causes some confusion at first notice).

That's right, I find it confusing at first.

>
> ....
>>>> Why does this fail:
>>>>  > r = as.raw(TRUE) > ifelse(TRUE, r, r) => error
>>>> This gives an error which I take for saying that raw cannot be coerced
>>>> to logical, but yes it can:
>>>>  > as.logical(r) => TRUE
>  
> Wrong. Or rather, irrelevant. The error is
> > ifelse(TRUE,r,r)
> Error in ans[test & !nas] <- rep(yes, length.out = length(ans))[test & 
> :  incompatible types (from raw to logical) in subassignment type fix
> Notice "subassignment type fix". This corresponds to this sort of 
> operation
> > r <- as.raw(TRUE)
> > x <- TRUE
> > x[1] <- r
> Error in x[1] <- r :  incompatible types (from raw to logical) in 
> subassignment type fix
> Now, notice that when the coercion is "bigger to smaller" the fix is 
> to coerce on the left side

What do you mean by "coercion from bigger to smaller"? What I thought 
should happen in the example above is to have x coerced upwards to logical.

>
> > y <- rep(TRUE,5)
> > y[1] <- 5
> > y
> [1] 5 1 1 1 1
>
> So the thing that might be expected here would be that x be coerced to 
> raw before the assignment, 

No, I would expect upwards coercion, just as in the example immediately 
above. I would expect r to be coerced to logical.


> but this is not implemented. I.e. you could have had the effect of.
> > x <- as.raw(x)
> > x[1] <- r
> > x
> [1] 01

No, I would rather expect to have the effect of:

 > x[1] <- as.logical(r)


>
> This is designed not to happen automatically. I didn't write the code 
> but I suppose one possible reason is that the raw mode does not allow 
> missing values (or negative numbers for that matter, everything is 
> 0-255).
> It also cuts the other way - no subassignment fixes are defined for 
> "raw":
> > x <- as.raw(1:10)
> > x[3] <- NA
> Error in x[3] <- NA :  incompatible types (from logical to raw) in 
> subassignment type fix
> > x[3] <- TRUE
> Error in x[3] <- TRUE :  incompatible types (from logical to raw) in 
> subassignment type fix
> > x[3] <- 4
> Error in x[3] <- 4 :  incompatible types (from double to raw) in 
> subassignment type fix
> > x[3] <- 4L
> Error in x[3] <- 4L :  incompatible types (from integer to raw) in 
> subassignment type fix
>

I don't understand any of these. If you can do the following:

 > as.raw(TRUE) => 1
 > as.raw(4L) => 04
 > as.raw(-1) => 00, with a warning
 > as.raw(NA) => 00, with a warning

Why can't this be done automatically. What would be wrong in having this 
done automatically, with a warning if needed?

>  
>>>>
>>>> and raw can even be used as the condition vector in ifelse:
>>>>  > ifelse(r, 1, 2) => 1
>
> Yes, but that's a different issue. Ifelse has the C language 
> convention that anything nonzero is TRUE.
> > ifelse(pi,2,1)
> [1] 2
>  

That's a news for me. The man page does not explain that!  It says 
"test: an object which can be coerced to logical mode" and also "Missing 
values in test give missing values in the result".  If ifelse were 
working the C way, I would expect 1 as the result here:

 > ifelse(as.raw(1), 1, 2) => error
 > as.raw(1) == 0 => FALSE

The raw 1 is nonzero.

Best regards,
Craig




More information about the R-help mailing list