[R] Cannot be coerced to logical?
Marc Schwartz
MSchwartz at mn.rr.com
Mon Oct 30 04:47:06 CET 2006
On Sun, 2006-10-29 at 18:34 -0800, Tova Fuller wrote:
> Hello all,
>
> So I am having a puzzling problem. I am working with a 534 x 1065
> data frame entitled LocalMaxExpBlue.COR which is completely full of
> logical values "TRUE" and "FALSE." However, when I attempt to
> manipulate this data frame, R does not recognize it as logical.
> Strangely enough, it will identify individual columns (but not rows)
> as logical. It will also identify all of the individual elements of
> each row as logical. Here are some examples:
>
> > is.logical(LocalMaxExpBlue.COR)
> [1] FALSE
>
> > is.logical(LocalMaxExpBlue.COR[,1])
> [1] TRUE
>
> > is.logical(LocalMaxExpBlue.COR[1,])
> [1] FALSE
>
> # If we look at the first five values of the first row, we notice
> that each value is indeed logical:
> > LocalMaxExpBlue.COR[1,c(1:5)]
> X1 X2 X3 X4 X5
> 1 FALSE FALSE FALSE FALSE FALSE
>
> # However, it does not recognize this!:
> > is.logical(LocalMaxExpBlue.COR[1,c(1:5)])
> [1] FALSE
>
> # It does recognize that individual values of each row are logical:
> > is.logical(LocalMaxExpBlue.COR[1,1])
> [1] TRUE
> > is.logical(LocalMaxExpBlue.COR[1,2])
> [1] TRUE
> # etc.
>
> Thank you in advance for your help. Perhaps I have made some small
> obvious mistake.
is.logical() is a generic method and knows nothing about logical data
frames. So in any of your subsetting where you are including multiple
columns, it is going to return FALSE. Keep in mind that data frames are
a list. As long as you are passing is.logical() vectors (ie. individual
columns or parts of individual columns), you are OK.
Depending upon what you are doing with the data, the easiest thing is
just to convert the data frame to a logical matrix.
For example, I created a data frame with all logical columns, similar to
yours:
> str(DF)
'data.frame': 534 obs. of 1065 variables:
$ V1 : logi TRUE FALSE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE TRUE FALSE ...
$ V2 : logi TRUE TRUE FALSE TRUE TRUE TRUE FALSE TRUE TRUE TRUE TRUE FALSE ...
$ V3 : logi TRUE FALSE FALSE TRUE FALSE TRUE FALSE TRUE FALSE FALSE TRUE FALSE ...
$ V4 : logi TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE ...
$ V5 : logi TRUE FALSE FALSE FALSE FALSE FALSE TRUE FALSE TRUE TRUE FALSE FALSE ...
$ V6 : logi FALSE FALSE FALSE FALSE TRUE FALSE FALSE FALSE TRUE TRUE FALSE FALSE ...
$ V7 : logi TRUE FALSE FALSE TRUE TRUE FALSE TRUE TRUE FALSE TRUE FALSE TRUE ...
$ V8 : logi TRUE TRUE FALSE TRUE TRUE FALSE TRUE FALSE FALSE FALSE TRUE TRUE ...
$ V9 : logi TRUE TRUE FALSE TRUE FALSE TRUE TRUE TRUE TRUE FALSE FALSE TRUE ...
$ V10 : logi TRUE FALSE FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE FALSE ...
> is.logical(DF)
[1] FALSE
> is.list(DF)
[1] TRUE
> mat <- as.matrix(DF)
> str(mat)
logi [1:534, 1:1065] TRUE FALSE TRUE FALSE TRUE FALSE TRUE TRUE
TRUE TRUE TRUE FALSE ...
- attr(*, "dimnames")=List of 2
..$ : chr [1:534] "1" "2" "3" "4" ...
..$ : chr [1:1065] "V1" "V2" "V3" "V4" ...
> is.logical(mat)
[1] TRUE
Since DF is a list, you can also do the following:
> all(sapply(DF, is.logical))
[1] TRUE
Since the individual columns will be passed as a vector to is.logical(),
if all() of the values come back as TRUE, then the result of the above
will be TRUE. See ?sapply and ?all for more information.
You can also extend is.logical() by creating a data frame method for it.
Again, we now start at the beginning:
> is.logical(DF)
[1] FALSE
Create a data frame method, based upon our function above:
> methods(is.logical)
no methods were found
# Create a new method
is.logical.data.frame <- function(x) {all(sapply(x, is.logical))}
> methods(is.logical)
[1] is.logical.data.frame
> is.logical(DF)
[1] TRUE
So, now is.logical() has a method for data frames and will return the
correct result.
HTH,
Marc Schwartz
More information about the R-help
mailing list