Reputation: 296
So, I discovered this:
> TRUE == "TRUE"
[1] TRUE
> TRUE == "BOO"
[1] FALSE
> TRUE == "true"
[1] FALSE
> TRUE == "T"
[1] FALSE
> FALSE == "FALSE"
[1] TRUE
> FALSE == "F"
[1] FALSE
According to the R documentation for logical {base}
:
as.logical attempts to coerce its argument to be of logical type. Character strings c("T", "TRUE", "True", "true") are regarded as true, c("F", "FALSE", "False", "false") as false, and all others as NA.
This is actually the case:
> as.logical("T")
[1] TRUE
So apparently, what's going on with TRUE == "T"
is not an as.logical
sort of conversion. Is there any reasonable explanation for the behavior of these == comparisons?
Upvotes: 7
Views: 10815
Reputation: 3140
Better to use isTRUE
> isTRUE
function (x)
identical(TRUE, x)
<bytecode: 0x82228c8>
<environment: namespace:base>
> isTRUE("T")
[1] FALSE
> isTRUE(T)
[1] TRUE
> isTRUE(TRUE)
[1] TRUE
> isTRUE("TRUE")
[1] FALSE
> isTRUE("anything")
[1] FALSE
> isTRUE(1L)
[1] FALSE
> isTRUE(c(TRUE,TRUE))
[1] FALSE
>
> isTRUE(any(c(TRUE,TRUE)))
[1] TRUE
> isTRUE(all(c(TRUE,TRUE)))
[1] TRUE
> answer <- "yes"
> isTRUE(answer %in% c("Y","Yes","y","yes"))
[1] TRUE
> answer <- "no"
> isTRUE(answer %in% c("Y","Yes","y","yes"))
[1] FALSE
> answer <- c("Y","n")
> isTRUE(answer %in% c("Y","Yes","y","yes"))
[1] FALSE
Upvotes: 1
Reputation: 2722
In terms of your question I'm having trouble imagining a scenario in which you would evaluate TRUE == "TRUE"
, vs "TRUE" == TRUE
. For instance; take a wrapper function that we can run all scenarios for your variables and iterate them through tests for as.logical, is.logical, x == TRUE, x == FALSE, x != TRUE
etc...
What our testing function will do is take an input and only return the scenarios that evaluate to TRUE
in terms of a logical test in an R function.
f <-function(var){
do_fun <- list(
`%s == TRUE` = function(x)x==TRUE,
`%s == FALSE` = function(x)x == FALSE,
`as.logical(%s)` = function(x)as.logical(x),
`is.logical(%s)` = function(x)is.logical(x))
a <- sapply(names(do_fun), function(i){
do.call(do_fun[[i]],list(var))
})
set_name <- sprintf(names(a),var)
a <- as.list(a)
names(a) <- set_name
a[sapply(a,`[`,1)]
}
Testing on TRUE
# from base test to show
> is.logical(TRUE)
[1] TRUE
Now with our testing fun
> f(TRUE)
$`TRUE == TRUE`
[1] TRUE
$`as.logical(TRUE)`
[1] TRUE
$`is.logical(TRUE)`
[1] TRUE
As strings instead of reserved characters
> f("true")
$`as.logical("true")`
[1] TRUE
> f("TRUE")
$`"TRUE" == TRUE`
[1] TRUE
$`as.logical("TRUE")`
[1] TRUE
On numeric values the output logical is based on the evaluation of the input rather than the class
> f(10.1)
$`as.logical(10.1)`
[1] TRUE
> f(10.1 > 1)
$`TRUE == TRUE`
[1] TRUE
$`as.logical(TRUE)`
[1] TRUE
$`is.logical(TRUE)`
[1] TRUE
> f(1+1)
$`as.logical(2)`
[1] TRUE
Upvotes: 3
Reputation: 2140
Here's what I made of it:
From the documentation of logical comparisons ?"=="
:
At least one of x and y must be an atomic vector, but if the other is a list R attempts to coerce it to the type of the atomic vector: this will succeed if the list is made up of elements of length one that can be coerced to the correct type. If the two arguments are atomic vectors of different types, one is coerced to the type of the other, the (decreasing) order of precedence being character, complex, numeric, integer, logical and raw.
To me it seems like the latter part of this is at work here. TRUE
is being coerced to "TRUE"
and the actual comparison becomes "TRUE"=="TRUE"
instead of TRUE==TRUE
.
T
always gets converted to TRUE
so T=="TRUE"
holds. However ``"T"` has no such luck when conversion is to happen to.character and not to.logical. .
Upvotes: 4