Reputation: 1635
I'm looking to generate all possible binary vectors of length n
in R. What is the best way (preferably both computationally efficient and readable code) to do this?
Upvotes: 3
Views: 4109
Reputation: 32548
n = 3
expand.grid(replicate(n, 0:1, simplify = FALSE))
# Var1 Var2 Var3
#1 0 0 0
#2 1 0 0
#3 0 1 0
#4 1 1 0
#5 0 0 1
#6 1 0 1
#7 0 1 1
#8 1 1 1
Upvotes: 10
Reputation: 5536
You should define what is "the best way" (fastest? shortest code?, etc.).
One way is to use the package R.utils
and the function intToBin
for converting decimal numbers to binary numbers. See the example.
require(R.utils)
n <- 5
strsplit(intToBin(0:(2 ^ n - 1)), split = "")
Upvotes: 0
Reputation: 1635
Inspired by this question generating all possible binary vectors of length n
containing less than m
1s, I've extended this code to produce all possible combinations. It's not pretty, though.
> z <- 3
> z <- rep(0, n)
> do.call(rbind, lapply(0:n, function(i) t(apply(combn(1:n,i), 2, function(k) {z[k]=1;z}))))
[,1] [,2] [,3]
[1,] 0 0 0
[2,] 1 0 0
[3,] 0 1 0
[4,] 0 0 1
[5,] 1 1 0
[6,] 1 0 1
[7,] 0 1 1
[8,] 1 1 1
What is it doing? Once we strip it back, the core of this one-liner is the following:
apply(combn(1:n,i), 2, function(k) {z[k]=1;z})
To understand this, let's step back one level further. The function combn(x,m)
generates all possible combinations of x
taken m
at a time.
> combn(1:n, 1)
[,1] [,2] [,3]
[1,] 1 2 3
> combn(1:n, 2)
[,1] [,2] [,3]
[1,] 1 1 2
[2,] 2 3 3
> combn(1:n, 3)
[,1]
[1,] 1
[2,] 2
[3,] 3
For using apply(MARGIN=2)
, we pass in a column of this function at a time to our inner function function(k) {z[k]=1;z}
which simply replaces all of the values at the indices k
with 1
. Since they were originally all 0
, this gives us each possible binary vector.
The rest is just window dressing. combn
gives us a wide, short matrix; we transpose it with t
. lapply
returns a list; we bind the matrices in each element of the list together with do.call(rbind, .)
.
Upvotes: 0