Phil Goetz Phil Goetz - 25 days ago 6
R Question

R: Why will as.character convert int matrix to char, but as.integer won't convert char matrix to int?

The "as.X" operators usually convert one type to another, but as.integer fails when applied to an array. Is this a bug? This is Microsoft R Open version 3.3 64-bit, and also R Foundation's R 3.3.1 for i686-pc-cygwin (32-bit).

> m <- matrix(rnorm(25), 5)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] -0.5958330 -0.3139274 -0.4746246 0.2431716 -0.5245235
[2,] 0.5677058 0.1944457 -2.3786936 0.2516587 -0.3541963
[3,] 0.6763564 -1.7285476 -0.5878008 -1.2277048 0.7737145
[4,] -1.4607755 -0.4761012 1.0995414 0.6978072 0.6120277
[5,] 0.8593707 0.2962030 1.1791963 -0.2276658 1.1559314
> m[] <- as.integer(m)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] 0 0 0 0 0
[2,] 0 0 -2 0 0
[3,] 0 -1 0 -1 0
[4,] -1 0 1 0 0
[5,] 0 0 1 0 1
> m[] <- as.character(m)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] "0" "0" "0" "0" "0"
[2,] "0" "0" "-2" "0" "0"
[3,] "0" "-1" "0" "-1" "0"
[4,] "-1" "0" "1" "0" "0"
[5,] "0" "0" "1" "0" "1"
> m[] <- as.integer(m)
> m
[,1] [,2] [,3] [,4] [,5]
[1,] "0" "0" "0" "0" "0"
[2,] "0" "0" "-2" "0" "0"
[3,] "0" "-1" "0" "-1" "0"
[4,] "-1" "0" "1" "0" "0"
[5,] "0" "0" "1" "0" "1"

Answer

The documentation states:

When an index expression appears on the left side of an assignment (known as subassignment) then that part of x is set to the value of the right hand side of the assignment. In this case no partial matching of character indices is done, and the left-hand-side is coerced as needed to accept the values. For vectors, the answer will be of the higher of the types of x and value in the hierarchy raw < logical < integer < double < complex < character < list < expression.

The behavior you see with subassignment on the left is consistent with that documented behavior.

Note that even though as.integer "works" in this case when directly applied to a double matrix, it still follows the type hierarchy and only rounds:

> m <- matrix(rnorm(25), 5)
> str(m)
 num [1:5, 1:5] 1.3807 -0.0858 1.4478 0.9509 0.6397 ...
> typeof(m)
[1] "double"
> m[] <- as.integer(m)
> str(m)
 num [1:5, 1:5] 1 0 1 0 0 0 0 0 -1 -1 ...
> typeof(m)
[1] "double"

Finally, as.integer often does not convert characters to valid integers:

> str(as.integer("a"))
 int NA
Warning message:
In str(as.integer("a")) : NAs introduced by coercion

...except that it results in the integer flavor of NA, namely NA_integer_. But it will convert characters to integers, as long as there is no subassignment:

> str(as.integer("1"))
 int 1

To address the comment about vectors, the documented behavior is the same on regular vectors:

> x <- rnorm(5)
> x[] <- as.character(x)
> x
[1] "0.687551073804054"  "-1.17843752343875"  "0.144747745284427"  "-0.931480738737143" "0.394279275668583" 
> x[] <- as.integer(x)
> x
[1] "0"  "-1" "0"  "0"  "0"