2

It appears that as.character() of a number is still a number, which I find counter intuitive. Consider this example:

1 > "2"
[1] FALSE
2 > "1"
[1] TRUE

Even if I try to use as.character() or paste()

as.character(2)
[1] "2"
as.character(2) > 1
[1] TRUE
as.character(2) < 1
[1] FALSE

Why is that? Can't I have R return an error when I am comparing numbers with strings?

Cettt
  • 11,460
  • 7
  • 35
  • 58
Masood Sadat
  • 1,247
  • 11
  • 18
  • **as.character represents real and complex numbers to 15 significant digits** <== From the docs. Maybe use an `expression` instead? What is your ultimate goal? – NelsonGon Jul 18 '19 at 08:08
  • @NelsonGon this behavior caused some problem in a lengthy function. I was not expecting comparison between numbers and characters would throw an error, but didn't. – Masood Sadat Jul 18 '19 at 08:15
  • 1
    This probably answers the question https://stackoverflow.com/questions/14932015/why-true-true-is-true-in-r The important part is `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.` – Ronak Shah Jul 18 '19 at 08:17
  • 2
    You might want to check out `"2" > 11`. The reason why this works as it does is basically the same as why `paste0("A", 1)` or `1L + 0.1` works. R changes the types when needed. – Roland Jul 18 '19 at 08:34
  • If as.character indeed forms numbers, what then is the hierarchy in this case? Is it a case of doing what comparison does(coerce) or simply as.character returning a numeric and the comparison made based on that? @Roland – NelsonGon Jul 18 '19 at 08:50
  • 1
    @NelsonGon `as.character` of course creates characters. What than happens is that `>` coerces the number to `character` and these characters are compared according to the collating sequence as the documentation explains. – Roland Jul 18 '19 at 09:01
  • Thanks. Just a bit confused. The documentation for `as. character` talks of some representation of real and complex numbers so I naively thought what would happen would be for as.charcater to form an integer repr of the string and then this would be used for comparison. I must have misunderstood that. @Roland – NelsonGon Jul 18 '19 at 09:03

2 Answers2

4

As explained in the comments the problem is that the numeric 1 is coerced to character. The operation < still works for characters. A character is smaller than another if it comes first in alphabetical order.

> "a" < "b"
[1] TRUE
> "z" < "b"
[1] FALSE

So in your case as.character(2) > 1 is transformed to as.character(2) > as.character(1) and because of the "alphabetical" order of numbers TRUEis returned.

To prevent this you would have to check for the class of an object manually.

Cettt
  • 11,460
  • 7
  • 35
  • 58
3

The documentation of ?Comparison states that

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.

So in your case the number is automatically coerced to string and the comparison is made based on the respective collation.

In order to prevent it, the only option I know of is to manually compare the class first.

AEF
  • 5,408
  • 1
  • 16
  • 30