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

Peter Dalgaard p.dalgaard at biostat.ku.dk
Fri Jun 26 23:27:59 CEST 2009


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).

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).


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

 > 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, but this is not implemented. I.e. you could 
have had the effect of.

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

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




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



-- 
    O__  ---- Peter Dalgaard             Øster Farimagsgade 5, Entr.B
   c/ /'_ --- Dept. of Biostatistics     PO Box 2099, 1014 Cph. K
  (*) \(*) -- University of Copenhagen   Denmark      Ph:  (+45) 35327918
~~~~~~~~~~ - (p.dalgaard at biostat.ku.dk)              FAX: (+45) 35327907




More information about the R-help mailing list