简体   繁体   中英

Create list of (NxN) martices with all combination of 0s and 1s R language

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM