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 n
cells) 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
Remove All of X Axis Labels in Ggplot
What's the Difference Between '1L' and '1'
R Command for Setting Working Directory to Source File Location in Rstudio
Sending Email in R via Outlook
Shiny: Differencebetween Observeevent and Eventreactive
Difference Between Passing Options in Aes() and Outside of It in Ggplot2
Line Break When No Data in Ggplot2
Generate Random Numbers with Fixed Mean and Sd
Why Is Allow.Cartesian Required at Times When When Joining Data.Tables with Duplicate Keys
Why Is Apply() Method Slower Than a for Loop in R
Avoid Ggplot Sorting the X-Axis While Plotting Geom_Bar()
What Does the Capital Letter "I" in R Linear Regression Formula Mean
Explain Ggplot2 Warning: "Removed K Rows Containing Missing Values"
Why am I Getting X. in My Column Names When Reading a Data Frame
Scraping a Dynamic Ecommerce Page with Infinite Scroll