I'm totally beginner in R language and it would be nice to get some hints from you guys.
I need to create list of all possible combination of matrices which elements will be 0s and 1s. These matrices need to have the same number of rows and columns.
For example in 2x2 matrices case there will be 4^2 = 16 possibilities.
Your question inspired me to try to write a generic function that can generate a list of all matrices of dimension nr
by nc
that can be formed with the elements of a given vector x
. Here's the result:
allmatrices <- function(x,nr,nc,...) {
nx <- length(x);
divs <- nx^seq(0L,nr*nc-1L);
lapply(seq(0L,nx^(nr*nc)-1L),function(i) matrix(x[i%/%divs%%nx+1L],nr,...));
}; ## end allmatrices()
Here's how you can use it to generate your required binary 2x2 matrix:
allmatrices(0:1,2L,2L);
## [[1]]
## [,1] [,2]
## [1,] 0 0
## [2,] 0 0
##
## [[2]]
## [,1] [,2]
## [1,] 1 0
## [2,] 0 0
##
## [[3]]
## [,1] [,2]
## [1,] 0 0
## [2,] 1 0
##
## [[4]]
## [,1] [,2]
## [1,] 1 0
## [2,] 1 0
##
## [[5]]
## [,1] [,2]
## [1,] 0 1
## [2,] 0 0
##
## [[6]]
## [,1] [,2]
## [1,] 1 1
## [2,] 0 0
##
## [[7]]
## [,1] [,2]
## [1,] 0 1
## [2,] 1 0
##
## [[8]]
## [,1] [,2]
## [1,] 1 1
## [2,] 1 0
##
## [[9]]
## [,1] [,2]
## [1,] 0 0
## [2,] 0 1
##
## [[10]]
## [,1] [,2]
## [1,] 1 0
## [2,] 0 1
##
## [[11]]
## [,1] [,2]
## [1,] 0 0
## [2,] 1 1
##
## [[12]]
## [,1] [,2]
## [1,] 1 0
## [2,] 1 1
##
## [[13]]
## [,1] [,2]
## [1,] 0 1
## [2,] 0 1
##
## [[14]]
## [,1] [,2]
## [1,] 1 1
## [2,] 0 1
##
## [[15]]
## [,1] [,2]
## [1,] 0 1
## [2,] 1 1
##
## [[16]]
## [,1] [,2]
## [1,] 1 1
## [2,] 1 1
Note that this results in identical output to the clever solution given by @alexis_laz in his comment:
identical(allmatrices(0:1,2L,2L),{ n <- 2; lapply(0:(((n*n)^2)-1),function(i) matrix(as.integer(head(intToBits(i),n*n)),n,n)); });
## [1] TRUE
And here's another example generating a list of 2x3 matrices formed with the first three letters:
allmatrices(letters[1:3],2L,3L);
## [[1]]
## [,1] [,2] [,3]
## [1,] "a" "a" "a"
## [2,] "a" "a" "a"
##
## [[2]]
## [,1] [,2] [,3]
## [1,] "b" "a" "a"
## [2,] "a" "a" "a"
##
## [[3]]
## [,1] [,2] [,3]
## [1,] "c" "a" "a"
## [2,] "a" "a" "a"
##
## [[4]]
## [,1] [,2] [,3]
## [1,] "a" "a" "a"
## [2,] "b" "a" "a"
##
## [[5]]
## [,1] [,2] [,3]
## [1,] "b" "a" "a"
## [2,] "b" "a" "a"
##
## [[6]]
## [,1] [,2] [,3]
## [1,] "c" "a" "a"
## [2,] "b" "a" "a"
##
## [[7]]
## [,1] [,2] [,3]
## [1,] "a" "a" "a"
## [2,] "c" "a" "a"
##
## [[8]]
## [,1] [,2] [,3]
## [1,] "b" "a" "a"
## [2,] "c" "a" "a"
##
## [[9]]
## [,1] [,2] [,3]
## [1,] "c" "a" "a"
## [2,] "c" "a" "a"
##
## [[10]]
## [,1] [,2] [,3]
## [1,] "a" "b" "a"
## [2,] "a" "a" "a"
##
## [[11]]
## [,1] [,2] [,3]
## [1,] "b" "b" "a"
## [2,] "a" "a" "a"
##
## ... snip ...
##
## [[719]]
## [,1] [,2] [,3]
## [1,] "b" "b" "c"
## [2,] "c" "c" "c"
##
## [[720]]
## [,1] [,2] [,3]
## [1,] "c" "b" "c"
## [2,] "c" "c" "c"
##
## [[721]]
## [,1] [,2] [,3]
## [1,] "a" "c" "c"
## [2,] "a" "c" "c"
##
## [[722]]
## [,1] [,2] [,3]
## [1,] "b" "c" "c"
## [2,] "a" "c" "c"
##
## [[723]]
## [,1] [,2] [,3]
## [1,] "c" "c" "c"
## [2,] "a" "c" "c"
##
## [[724]]
## [,1] [,2] [,3]
## [1,] "a" "c" "c"
## [2,] "b" "c" "c"
##
## [[725]]
## [,1] [,2] [,3]
## [1,] "b" "c" "c"
## [2,] "b" "c" "c"
##
## [[726]]
## [,1] [,2] [,3]
## [1,] "c" "c" "c"
## [2,] "b" "c" "c"
##
## [[727]]
## [,1] [,2] [,3]
## [1,] "a" "c" "c"
## [2,] "c" "c" "c"
##
## [[728]]
## [,1] [,2] [,3]
## [1,] "b" "c" "c"
## [2,] "c" "c" "c"
##
## [[729]]
## [,1] [,2] [,3]
## [1,] "c" "c" "c"
## [2,] "c" "c" "c"
As you can see, this algorithm balloons out of control real fast. Be careful!
In addition to parameterizing the cell values and the dimensions, I also pass variadic arguments to the matrix()
calls, providing a little more flexibility. So, for example, you can fill the matrices byrow
rather than by column, and pass dimension names if you want:
allmatrices(0:1,2L,2L,byrow=T,dimnames=list(letters[3:4],letters[1:2]));
## [[1]]
## a b
## c 0 0
## d 0 0
##
## [[2]]
## a b
## c 1 0
## d 0 0
##
## [[3]]
## a b
## c 0 1
## d 0 0
##
## [[4]]
## a b
## c 1 1
## d 0 0
##
## [[5]]
## a b
## c 0 0
## d 1 0
##
## [[6]]
## a b
## c 1 0
## d 1 0
##
## [[7]]
## a b
## c 0 1
## d 1 0
##
## [[8]]
## a b
## c 1 1
## d 1 0
##
## [[9]]
## a b
## c 0 0
## d 0 1
##
## [[10]]
## a b
## c 1 0
## d 0 1
##
## [[11]]
## a b
## c 0 1
## d 0 1
##
## [[12]]
## a b
## c 1 1
## d 0 1
##
## [[13]]
## a b
## c 0 0
## d 1 1
##
## [[14]]
## a b
## c 1 0
## d 1 1
##
## [[15]]
## a b
## c 0 1
## d 1 1
##
## [[16]]
## a b
## c 1 1
## d 1 1
Performance testing:
library(microbenchmark);
bgoldst <- function() allmatrices(0:1,2L,2L);
alexis <- function() { n <- 2; lapply(0:(((n*n)^2)-1),function(i) matrix(as.integer(head(intToBits(i),n*n)),n,n)); };
identical(bgoldst(),alexis());
## [1] TRUE
microbenchmark(bgoldst(),alexis(),times=1000L);
## Unit: microseconds
## expr min lq mean median uq max neval
## bgoldst() 62.865 70.136 80.15788 73.130 77.4060 1029.362 1000
## alexis() 187.741 205.702 229.48292 217.677 226.8705 1261.150 1000
It's likely the
intToBits()
/
as.integer()
conversion that's costing @alexis_laz's solution some speed.
Edit: Well-played, @alexis_laz! You win this round:
alexis <- function() { n <- 2; lapply(0:(((n*n)^2)-1),function(i) matrix(as.integer(intToBits(i)[seq_len(n*n)]),n,n)); };
identical(bgoldst(),alexis());
## [1] TRUE
microbenchmark(bgoldst(),alexis(),times=1000L);
## Unit: microseconds
## expr min lq mean median uq max neval
## bgoldst() 64.148 70.136 77.98883 72.702 77.4055 1093.083 1000
## alexis() 48.325 54.313 63.70390 56.878 61.1550 3271.121 1000
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.