'Is abind console output incorrect?
I am trying to combine multiple 2d vectors to obtain a 3dvector, the 3d vector should be [rows, columns, 2dvectors]. So far I have only worked with 3d vectors made from a only one 2d vector:
x <- matrix(1:12, 3,4)
# [,1] [,2] [,3] [,4]
#[1,] 1 4 7 10
#[2,] 2 5 8 11
#[3,] 3 6 9 12
dim(x) <- c(dim(x), 1))
dim(x)
#[1] 3 4 1
And when I select a row shows this:
x[1,,]
#[1] 1 4 7 10
Now to combine 2d vectors into a 3d vector I have done as follow:
x <- matrix(1:12, 3, 4)
y <- x + 100
z <- abind(x, y, along=3)
dim(z)
#[1] 3 4 2
As you can see the dimensions are correct [rows, columns, 2dvectors]. Therefore I expect this:
z[1,,]
# [,1] [,2] [,3] [,4]
#[1,] 1 4 7 10
#[2,] 101 104 107 110
But instead I get this:
z[1,,]
# [,1] [,2]
#[1,] 1 101
#[2,] 4 104
#[3,] 7 107
#[4,] 10 110
So I want to know if is the output displaying correctly at the console or if there is something I am not understanding.
Solution 1:[1]
There might be several confusing aspects that lead to the unexpected output:
- A
matrix
in R is restricted to two-dimensional matrices, and in factis.matrix(...)
returnsTRUE
ifdim(...) <= 2
. Matrices with higher dimensions are actually calledarray
. Consider
x <- matrix(1:12, 3,4)
class(x) # x is matrix, array
# [1] "matrix" "array"
dim(x) <- c(dim(x), 1))
dim(x)
# [1] 3 4 1
class(x) # x is array
# [1] "array"
- Extract or replace parts of an object (that is, slicing of a matrix) with bracket-notation like
x[1,,]
involves a default parameterdrop = TRUE
.
For matrices and arrays, if
drop = TRUE
, then the result is coerced to the lowest possible dimension.
When drop = FALSE
, function drop(...)
will NOT be invoked at all, that is x[1,,,drop=FALSE]
will has its dim(...)
as c(1,4,1)
, and console output turns into:
x[1,,,drop=FALSE]
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
Then the abind
output appears more consistent:
y <- x + 100
z <- abind(x, y, along=3)
dim(z)
# [1] 3 4 2
z[1,,,drop=FALSE]
# , , 1
#
# [,1] [,2] [,3] [,4]
# [1,] 1 4 7 10
#
# , , 2
#
# [,1] [,2] [,3] [,4]
# [1,] 101 104 107 110
- The way
drop(...)
works can be confusing too because it
Delete the dimensions of an array which have only one level.
that is, for x[1,,,drop=FALSE]
with dimensions c(1, 4, 1)
, drop(...)
will delete its first and third dimension, reducing dimensions to c(4)
. But will return NULL
instead, because dim(...)
is defined to return NULL
for a vector:
drop(x[1,,,drop=FALSE])
# [1] 1 4 7 10
class(drop(x[1,,,drop=FALSE]))
# [1] "integer"
dim(drop(x[1,,,drop=FALSE]))
# NULL
For z[1,,,drop=FALSE]
with dimensions c(1,4,2)
, drop(...)
will reduce its dimensions to c(4,2)
, like:
drop(z[1,,,drop=FALSE])
# [,1] [,2]
# [1,] 1 101
# [2,] 4 104
# [3,] 7 107
# [4,] 10 110
How to make drop(...)
more intuitive?
An alternative way of implementing drop(...)
might be more intuitive -- delete the heading dimensions of an array which have only one level. That is for an array with dimension like c(1,1,3,1,2,1)
, our drop2(...)
will reduce into c(3,1,2,1)
. As a crude implementation, consider
dummy = array(1:6, dim=c(1,1,3,1,2,1))
drop2 = function(x) {
x.dim = dim(x)
if (is.null(x.dim)) return(x)
array(x, dim=x.dim[cumsum(x.dim > 1) > 0])
}
dim(drop2(dummy))
# [1] 3 1 2 1
drop2(x[1,,,drop=FALSE]) # resulting dim c(4, 1)
# [,1]
# [1,] 1
# [2,] 4
# [3,] 7
# [4,] 10
drop2(z[1,,,drop=FALSE])
# [,1] [,2]
# [1,] 1 101
# [2,] 4 104
# [3,] 7 107
# [4,] 10 110
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |