Reputation: 605
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"
Upvotes: 0
Views: 319
Reputation: 605
Joran's answer gives the rule which causes this behavior. The reason for this rule is that a subassignment sometimes does and sometimes doesn't operate on the entire data structure. In cases when it does, it can't convert an entire vector or matrix's datatype. In the case of m[] = ..., it could, but it's better to behave the same way in all cases. Otherwise, it would introduce bugs in cases where a subassignment by indices just happened to cover an entire vector or matrix.
Upvotes: 0
Reputation: 226182
If you do want to "downcast" a matrix you might be interested in storage.mode()<-
:
> m <- matrix(1:4,2)
> m
[,1] [,2]
[1,] 1 3
[2,] 2 4
> storage.mode(m) <- "character"
> m
[,1] [,2]
[1,] "1" "3"
[2,] "2" "4"
> storage.mode(m) <- "integer"
> m
[,1] [,2]
[1,] 1 3
[2,] 2 4
Upvotes: 3
Reputation: 173577
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"
Upvotes: 6