subset and replace all nth elements from an array of vectors

blklempay Source

I am trying to generate a matrix where each element is a vector of length 2 and then fill the vectors automatically. What I have so far is:

dat <- matrix(list(vector("numeric",2)),3,3)
dat

##      [,1]      [,2]      [,3]     
## [1,] Numeric,2 Numeric,2 Numeric,2
## [2,] Numeric,2 Numeric,2 Numeric,2
## [3,] Numeric,2 Numeric,2 Numeric,2

I want to fill this empty matrix so that it looks something like this:

       [[,1]]   [[,2]]   [[,3]]     
[[1,]] [1] 1 1  [1] 1 2  [1] 1 3
[[2,]] [1] 2 1  [1] 2 2  [1] 2 3
[[3,]] [1] 3 1  [1] 3 2  [1] 3 3

I can subset and replace each element manually with the code dat[[1,1]] <- c(1,1) and I can subset all the first vector elements of dat with the code sapply(dat,"[", 1), but I can't then replace these vector elements with the desired values, e.g. sapply(dat,"[", 1) <- rep(1:3,3) (returns could not find function "sapply<-" error).

rmatrixvector

Answers

answered 1 year ago r2evans #1

Might I suggest you use a 3-D array instead?

ary <- array(1:18, dim=c(3,3,2))
ary
# , , 1
#      [,1] [,2] [,3]
# [1,]    1    4    7
# [2,]    2    5    8
# [3,]    3    6    9
# , , 2
#      [,1] [,2] [,3]
# [1,]   10   13   16
# [2,]   11   14   17
# [3,]   12   15   18

Reassignment of a single "pair". Note the trailing comma, similar to how mtcars[1,] returns all columns from the first row.

ary[1,1,] <- c(1, 1)
ary
# , , 1
#      [,1] [,2] [,3]
# [1,]    1    4    7
# [2,]    2    5    8
# [3,]    3    6    9
# , , 2
#      [,1] [,2] [,3]
# [1,]    1   13   16
# [2,]   11   14   17
# [3,]   12   15   18

To replace all first-values:

ary[,,1] <- rep(1:3, 3)
ary
# , , 1
#      [,1] [,2] [,3]
# [1,]    1    1    1
# [2,]    2    2    2
# [3,]    3    3    3
# , , 2
#      [,1] [,2] [,3]
# [1,]    1   13   16
# [2,]   11   14   17
# [3,]   12   15   18

In order to apply something over the matrix of paired values, you can use apply(ary, 1:2, ...), such as:

plot(NA, xlim=c(1,3), ylim=c(1,18))
apply(ary, c(1,2), function(pts) points(pts[1], pts[2]))

When you look at the MARGIN argument (c(1,2) here) of apply, it is saying "apply a function for each row,column 'set' of the data". When looking at a simple 2-D matrix, a margin of c(1,2) iterates the function over each individual value. In a 3-D array, it applies the function over each "pipe" of the matrix.

That apply call is equivalent to this sequence of function calls:

points(1, 1)
points(2, 11)
points(3, 12)
points(1, 13)
points(2, 14)
points(3, 15)
points(1, 16)
points(2, 17)
points(3, 18)

(This example could easily be accomplished with plot(ary[,,1], ary[,,2]), but that doesn't necessarily answer your need for a function that accepts the pair as a single argument. Similarly with mapply(points, ary[,,1], ary[,,2]).)

If your consuming function takes a vector of values, then perhaps this will work:

apply(ary, c(1,2), yourfunc)

comments powered by Disqus