I would like to access an array 3d with a matrix. Here an example of the desired output:
a <- array(1:18, dim=c(3,3,2))
a
, , 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
b <- array(1:2, dim=c(3,3))
b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
a[b]
[,1] [,2] [,3]
[1,] 1 13 7
[2,] 11 5 17
[3,] 3 15 9
(Should i pass a data frame with 3 columns (indexs + values) instead of a matrix?)
if i do a[b], this is the result:
a[b]
4 11 4
and why?
c <- array(1:2, dim=c(2,2))
a[c]
[1] 1 2 1 2
for b <- array(1:2, dim=c(3,3))
> b
[,1] [,2] [,3]
[1,] 1 2 1
[2,] 2 1 2
[3,] 1 2 1
the indices are read by rows. Thus, as #jogo mentioned, a[b] is actually c(a[1, 2, 1], a[2, 1, 2], a[1, 2, 1])
for C <- array(1:2, dim=c(2,2))
> C
[,1] [,2]
[1,] 1 1
[2,] 2 2
since the dimension of C does not match a (only two out of three fit), in this case a[C] is interpreted as a[c(C)] (thanks to comments from #jogo).
Related
The title with the following example should be self-explanatory:
m = unique(replicate(5, sample(1:5, 5, rep=F)), MARGIN = 2)
m
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 1 4 3
[2,] 5 1 5 1 2
[3,] 4 3 3 3 1
[4,] 3 4 4 5 5
[5,] 2 2 2 2 4
But what I want is instead:
[,1] [,2] [,3] [,4] [,5]
[1,] 1 1 3 4 5
[2,] 5 5 2 1 1
[3,] 3 4 1 3 3
[4,] 4 3 5 5 4
[5,] 2 2 4 2 2
Ideally, I would like to find a method that allows the same process to be carried out when the column vectors are words (alphabetic order).
I tried things like m[ , sort(m)] but nothing did the trick...
m[, order(m[1, ]) will order the columns by the first row. m[, order(m[1, ], m[2, ])] will order by the first row, using second row as tie-breaker. Getting fancy, m[, do.call(order, split(m, row(m)))] will order the columns by the first row, using all subsequent rows for tie-breakers. This will work character data just as well as numeric.
set.seed(47)
m = replicate(5, sample(1:5, 5, rep=F))
m
# [,1] [,2] [,3] [,4] [,5]
# [1,] 5 4 1 5 1
# [2,] 2 2 3 2 3
# [3,] 3 5 5 1 2
# [4,] 4 3 2 3 5
# [5,] 1 1 4 4 4
m[, do.call(order, split(m, row(m)))]
# [,1] [,2] [,3] [,4] [,5]
# [1,] 1 1 4 5 5
# [2,] 3 3 2 2 2
# [3,] 2 5 5 1 3
# [4,] 5 2 3 3 4
# [5,] 4 4 1 4 1
I know that I can make a simple matrix (for example 1->20 numbers, 4,5 rows) using this:
x<- array(1:20, dim=c(4,5)); x
But I have no idea how to make a matrix similar to the one on the picture...
matrix(rep(1:4,4)^rep(0:3,each=4), byrow=TRUE, nrow=4)
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 1 2 3 4
[3,] 1 4 9 16
[4,] 1 8 27 64
You can create a function if you want to be able to generate an analogous square matrix with an arbitrary number of rows.
power_mat = function(n) {
matrix(rep(1:n,n)^rep(1:n - 1, each=n), byrow=TRUE, nrow=n)
}
power_mat(6)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 1 1 1 1 1
[2,] 1 2 3 4 5 6
[3,] 1 4 9 16 25 36
[4,] 1 8 27 64 125 216
[5,] 1 16 81 256 625 1296
[6,] 1 32 243 1024 3125 7776
Solution
t(sapply(0:3, function(x) (1:4)^x))
Result
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 1 2 3 4
[3,] 1 4 9 16
[4,] 1 8 27 64
(You can easily verify this matches your matrix)
Explanation
Each row of the matrix is the vector c(1, 2, 3, 4) raised to the power of the row index (in a 0-based indexing system). So, we just use sapply() on the vector of powers to raise 1:4 to each power which will return a matrix. Because sapply() would return the results as column vectors, we use t() to transpose the result.
n <- 4
m <- 4
t(sapply( 0:(n-1), FUN = function (i){ return(c(1:m)**i) }))
where n is the number of rows, and m is the number of columns.
[,1] [,2] [,3] [,4]
[1,] 1 1 1 1
[2,] 1 2 3 4
[3,] 1 4 9 16
[4,] 1 8 27 64
n = 4
m = rbind(rep(1, n), t(replicate(n-1, 1:n)))
m ^ (row(m) - 1)
# [,1] [,2] [,3] [,4]
#[1,] 1 1 1 1
#[2,] 1 2 3 4
#[3,] 1 4 9 16
#[4,] 1 8 27 64
I have two matrices m1 and m2.
m1 <- matrix(1:16, ncol = 4)
m2 <- matrix(16:1, ncol = 4)
# > m1
# [,1] [,2] [,3] [,4]
# [1,] 1 5 9 13
# [2,] 2 6 10 14
# [3,] 3 7 11 15
# [4,] 4 8 12 16
# > m2
# [,1] [,2] [,3] [,4]
# [1,] 16 12 8 4
# [2,] 15 11 7 3
# [3,] 14 10 6 2
# [4,] 13 9 5 1
I want to find the minimum between the two matrices for each cell within a moving kernel of 3x3. The outer margines should be ignored, i.e. they can be filled with NAs and the min function should then have na.rm = TRUE. The result should look like this:
# > m3
# [,1] [,2] [,3] [,4]
# [1,] 1 1 3 3
# [2,] 1 1 2 2
# [3,] 2 2 1 1
# [4,] 3 3 1 1
I have already tried a combination of pmin{base} and runmin{caTools} like this:
pmin(runmin(m1, 3, endrule = "keep"),
runmin(m2, 3, endrule = "keep"))
However, this did not work. Probably due to the fact that
"If x is a matrix than each column will be processed separately."
(from ?runmin)
Is there any package, that performs such operations, or is it possible to apply?
Here is a base R approach:
m = pmin(m1, m2)
grid = expand.grid(seq(nrow(m)), seq(ncol(m)))
x = apply(grid, 1, function(u) {
min(m[max(1,u[1]-1):min(nrow(m), u[1]+1), max(1,u[2]-1):min(ncol(m), u[2]+1)])
})
dim(x) = dim(m)
#> x
# [,1] [,2] [,3] [,4]
#[1,] 1 1 3 3
#[2,] 1 1 2 2
#[3,] 2 2 1 1
#[4,] 3 3 1 1
Here I have a
x <- array(1:20, dim=c(4,5))
x
[,1] [,2] [,3] [,4] [,5]
[1,] 1 5 9 13 17
[2,] 2 6 10 14 18
[3,] 3 7 11 15 19
[4,] 4 8 12 16 20
I also have a index array
i <- array(c(1:3,3:1), dim=c(3,2))
[,1] [,2]
[1,] 1 3
[2,] 2 2
[3,] 3 1
Then
x[i]
will extract X[1,3], X[2,2] and X[3,1]
However, what if I have
i <- array(c(1:3,3:1), dim=c(2,3))
The output is
x[i]
[1] 1 2 3 3 2 1
How can I understand this result?
I have a list of matrices (with the same number of columns), say lst_Mat and I'd like to have all row-wise combinations of matrices in this list. For example, lst_Mat could be like this:
> lst_Mat
[[1]]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 3 2 4
[3,] 1 3 4 2
[4,] 2 1 3 4
[5,] 2 3 1 4
[6,] 2 3 4 1
[[2]]
[,1] [,2] [,3] [,4]
[1,] 1 3 2 4
[2,] 3 1 2 4
[3,] 3 2 1 4
[4,] 3 2 4 1
[[3]]
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 2 4 3
[3,] 1 3 2 4
[4,] 1 3 4 2
[5,] 1 4 2 3
[6,] 1 4 3 2
[7,] 2 1 3 4
[8,] 2 1 4 3
[9,] 2 3 1 4
[10,] 3 1 2 4
[[4]]
[,1] [,2] [,3] [,4]
[1,] 2 1 4 3
[2,] 2 3 1 4
[3,] 3 1 2 4
[4,] 3 1 4 2
[5,] 3 2 1 4
As such, the total number of combinations would be 6*4*10*5=1200. This problem is analogous to the problem of generating all possible strings of English letters (i.e. a, b, c,..., x, y, z) with a specific length. For instance: aaa, aab, aac,..., aaz, aba, abb,..., abz, aca,... and so on.
I have come up with the following solution:
lst_Mat_len=list()
C=ncol(lst_Mat[[1]])
for (i in 1:length(lst_Mat))
lst_Mat_len[[length(lst_Mat_len)+1]]=(1:nrow(lst_Mat[[i]]))
combs=do.call(expand.grid, lst_Mat_len)
for (i in 1:nrow(combs)){
M=matrix(0, 0, C)
for (j in 1:ncol(combs))
M=rbind(M, lst_Mat[[j]][combs[i,j],])
# print(M)
}
Sample output of M:
> M
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 3 2 4
[3,] 1 2 3 4
[4,] 2 1 4 3
> M
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 1 3 2 4
[3,] 1 2 3 4
[4,] 2 3 1 4
That is, one row per matrix, each time.
I'd appreciate any other algorithms for doing so.
Here is another solution, I changed a little bit the example to make it more reproducible:
ones <- t(rep(1, 4))
lst_Mat <- list(1:6 %*% ones, 7:11 %*% ones, 12:21 %*% ones, 22:26 %*% ones)
combs <- expand.grid( sapply(lst_Mat, function(x) 1:nrow(x)) )
nbcombs <- nrow(combs)
res <- NULL
for (i in 1:nbcombs)
res[[i]] <- t(mapply(function(mat,line) mat[line,], lst_Mat, combs[i, ]))