How to Generate a Matrix of Combinations

Generate a matrix containing all combinations of elements taken from n vectors

The ndgrid function almost gives the answer, but has one caveat: n output variables must be explicitly defined to call it. Since n is arbitrary, the best way is to use a comma-separated list (generated from a cell array with ncells) to serve as output. The resulting n matrices are then concatenated into the desired n-column matrix:

vectors = { [1 2], [3 6 9], [10 20] }; %// input data: cell array of vectors

n = numel(vectors); %// number of vectors
combs = cell(1,n); %// pre-define to generate comma-separated list
[combs{end:-1:1}] = ndgrid(vectors{end:-1:1}); %// the reverse order in these two
%// comma-separated lists is needed to produce the rows of the result matrix in
%// lexicographical order
combs = cat(n+1, combs{:}); %// concat the n n-dim arrays along dimension n+1
combs = reshape(combs,[],n); %// reshape to obtain desired matrix

How to generate a matrix of combinations

expand.grid(c(-1,1), c(-1,1), c(-1,1), c(-1,1), c(-1,1))

How to create a matrix from all possible combinations of 2 or more matrices?

You can use expand.grid() and take its output to index the matrix A and B,

x <- expand.grid(1:3,1:3)

cbind(A[x[,1],], B[x[,2],])

gives,

     [,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 0 0 1 0 0
[2,] 0 1 0 0 1 0
[3,] 0 0 1 0 0 1
[4,] 1 0 0 1 0 0
[5,] 0 1 0 0 1 0
[6,] 0 0 1 0 0 1
[7,] 1 0 0 1 0 0
[8,] 0 1 0 0 1 0
[9,] 0 0 1 0 0 1

EDIT:

For more than two matrices, you can use a function like below,

myfun <- function(...) {

arguments <- list(...)

a <- expand.grid(lapply(arguments, function(x) 1:nrow(x)))


do.call(cbind,lapply(seq(a),function(x) { arguments[[x]][a[,x],] }))


}

out <- myfun(A,B,C)

head(out)

gives,

     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 0 0 1 0 0 1 0 0 0
[2,] 0 1 0 1 0 0 1 0 0 0
[3,] 0 0 1 1 0 0 1 0 0 0
[4,] 1 0 0 0 1 0 1 0 0 0
[5,] 0 1 0 0 1 0 1 0 0 0
[6,] 0 0 1 0 1 0 1 0 0 0

Data:

A <- B <- diag(3)
C <- diag(4)

Python generate all possible combinations of matrix

One way is by generating all binary sequences of length m*n in a list comprehension, and reshaping them into a (m,n) shaped nested list on each iteration.

A simple way to generate all sequences is by taking the cartesian product of 01 with n*m repeats, which will be produce 2^(m*n) combinations:

from itertools import product
m=3
n=3

x = [[list(i[x:x+m]) for x in range(0, len(i), m)] for i in product("01", repeat=m*n)]

Output

[[['0' '0' '0']
['0' '0' '0']
['0' '0' '0']]

[['0' '0' '0']
['0' '0' '0']
['0' '0' '1']]

[['0' '0' '0']
['0' '0' '0']
['0' '1' '0']]
...

print(len(x))
# 512

generate all possible column combinations and create one matrix for each of them in R

Here is one way:

list.of.matrices <- apply(expand.grid(rep(list(c(FALSE, TRUE)), ncol(myarray))),
1, function(j)myarray[, j, drop = FALSE])

length(list.of.matrices)
# [1] 1024

Then do something like:

result <- sapply(list.of.matrices, function_of_your_choice)

but note that det can only be applied to square matrices... Please clarify.

How to generate all possible combinations of 0-1 matrix in Python?

A one-liner solution with numpy and itertools:

[np.reshape(np.array(i), (K, N)) for i in itertools.product([0, 1], repeat = K*N)]

Explanation: the product function returns a Cartesian product of its input. For instance, product([0, 1], [0, 1]) returns an iterator that comprises all possible permutations of [0, 1] and [0, 1]. In other words, drawing from a product iterator:

for i, j in product([0, 1], [0, 1]):

is actually equivalent to running two nested for-loops:

for i in [0, 1]:
for j in [0, 1]:

The for-loops above already solve the problem at hand for a specific case of K, N = (1, 0). Continuing the above line of thought, to generate all possible zero/one states of a vector i, we need to draw samples from an iterator that is equivalent to a nested for-loop of depth l, where l = len(i). Luckily, itertools provides the framework to do just that with its repeat keyword argument. In the case of OP's problem this permutation depth should be K*N, so that it can be reshaped into a numpy array of proper sizes during each step of the list comprehension.

create a matrix from combinations with values

Imagine if the "combinations" are stored in a file in the following format (or similar):

A,B,1
A,C,0
A,D,1
B,C,1
B,D,1
C,D,0

Then you can do:

df = pd.read_csv(filename, header=None)

Example (using your sample data):

txt = """A,B,1
A,C,0
A,D,1
B,C,1
B,D,1
C,D,0
"""
df = pd.read_csv(io.StringIO(txt), header=None)

Now df contains:

   0  1  2
0 A B 1
1 A C 0
2 A D 1
3 B C 1
4 B D 1
5 C D 0

From that point, a little bit of massaging will get you what you want:

# all labels (for rows and cols)
r = sorted(set(df[0]) | set(df[1]))

# upper triangular
z = (
df.set_index([0, 1])
.reindex(pd.MultiIndex.from_product([r, r]))
.squeeze()
.unstack(1)
)

# fill in the lower triangular part to make z symmetric
z = z.where(~z.isna(), z.T)

We get:

>>> z
A B C D
A NaN 1.0 0.0 1.0
B 1.0 NaN 1.0 1.0
C 0.0 1.0 NaN 0.0
D 1.0 1.0 0.0 NaN

Note: if you prefer to stay in int-only (and set the diagonal to 0), then:

z = (
df.set_index([0, 1])
.reindex(pd.MultiIndex.from_product([r, r]), fill_value=0)
.squeeze()
.unstack(1)
)
z += z.T

and now:

>>> z
A B C D
A 0 1 0 1
B 1 0 1 1
C 0 1 0 0
D 1 1 0 0

For speed

Now, if you know for sure that you are dealing with 4x4 matrices and that the order is exactly as you indicated (ordered by the upper triangle), you can do the following for a faster set up:

# get the triangular values, somehow (e.g. read file and discard
# all but the last value;

# here we simply take them from the df above:
tri = df[2].values # np.array([1, 0, 1, 1, 1, 0])

# and now, in pure numpy:
z = np.zeros((4,4), dtype=int)
z[np.triu_indices(4, 1)] = tri
z += z.T

The result is a simple numpy array (no labels):

>>> z
[[0 1 0 1]
[1 0 1 1]
[0 1 0 0]
[1 1 0 0]]

All possible combinations of matrices with values from vectors

This gives every possible combination of two elements from each set (where replacement is allowed), giving a total of 144 matrices. These are then bound together to give a single 288-row data frame:

A = c(1,2,3) 
B = c("x","z")
C = c(1,0)

df <- setNames(as.data.frame(do.call(rbind,
lapply(as.data.frame(t(expand.grid(A, B, C, A, B, C))),
matrix, nrow = 2, byrow = TRUE))),
c("A", "B", "C"))

head(df)
#> A B C
#> 1 1 x 1
#> 2 1 x 1
#> 3 2 x 1
#> 4 1 x 1
#> 5 3 x 1
#> 6 1 x 1

nrow(df)
#> [1] 288

Created on 2020-09-06 by the reprex package (v0.3.0)



Related Topics



Leave a reply



Submit