Reputation: 29
I would like to find all possible combinations of a matrix columns, with each column contributing a value, in each iteration of a loop. The matrix size changes in each iteration. For example:
A = [1 2 3
4 5 6
7 8 9].
should produce:
1 2 3
1 2 6
1 5 3
etc. but should not produce:
1 4 2
for example.
My problems:
When I insert the matrix to the combvec
function nothing happens. The function accepts vectors - and since I do it with a different matrix size in each iteration of a loop I can't write it manually.
ndgrid
also requires vectors - and since I need to choose a combination index in another variable, I'm not clear how this happens.
I don't have combination function in my Matlab version.
Is there a way to define vectors dynamically in a loop? Any idea on to how overcome this? Do I need to write a combination function myself?
I've tried used combvec
with a matrix - it returns the matrix itself without combinations.
Upvotes: 2
Views: 78
Reputation: 101335
combinations
+ num2cell
I think you can use num2cell
+ combinations
x = num2cell(A,1);
combinations(x{:})
which gives a table like below
ans =
27×3 table
Var1 Var2 Var3
____ ____ ____
1 2 3
1 2 6
1 2 9
1 5 3
1 5 6
1 5 9
1 8 3
1 8 6
1 8 9
4 2 3
4 2 6
4 2 9
4 5 3
4 5 6
4 5 9
4 8 3
4 8 6
4 8 9
7 2 3
7 2 6
7 2 9
7 5 3
7 5 6
7 5 9
7 8 3
7 8 6
7 8 9
If you are interested in customized coding, you can write a recursion with combvec
like below
function out = expandgrid(mat)
if iscolumn(mat)
out = mat.';
else
out = combvec(expandgrid(mat(:,1:end-1)), mat(:,end).');
end
end
and then run transpose(expandgrid(A))
, which gives
1 2 3
4 2 3
7 2 3
1 5 3
4 5 3
7 5 3
1 8 3
4 8 3
7 8 3
1 2 6
4 2 6
7 2 6
1 5 6
4 5 6
7 5 6
1 8 6
4 8 6
7 8 6
1 2 9
4 2 9
7 2 9
1 5 9
4 5 9
7 5 9
1 8 9
4 8 9
7 8 9
Or, you can use repmat
+ repelem
like below to define the recursion
function out = expandgrid(mat)
nr = size(mat,1);
if iscolumn(mat)
out = mat;
else
p = repmat(expandgrid(mat(:,1:end-1)), nr, 1);
q = repelem(mat(:,end), length(p)/nr);
out = [p, q];
end
end
and expandgrid(A)
can yield
1 2 3
4 2 3
7 2 3
1 5 3
4 5 3
7 5 3
1 8 3
4 8 3
7 8 3
1 2 6
4 2 6
7 2 6
1 5 6
4 5 6
7 5 6
1 8 6
4 8 6
7 8 6
1 2 9
4 2 9
7 2 9
1 5 9
4 5 9
7 5 9
1 8 9
4 8 9
7 8 9
Upvotes: 1
Reputation: 30046
combvec
accepts vectors, so split your matrix into a cell of vectors (one per column)
v = arrayfun( @(x) A(:,x).', (1:size(A,2)), 'uni', 0 );
[Edit: equivalent simpler suggestion from Luis' comment v = num2cell(A.', 2);
]
Then pass all of these vectors as individual inputs to combvec
:
c = combvec( v{:} ).';
Be wary if this is "dynamic" as A
wouldn't have to be much larger before your combinations output is significantly larger and your program will slow down significantly (or run out of RAM).
Output:
c =
1 2 3
4 2 3
7 2 3
1 5 3
4 5 3
7 5 3
1 8 3
4 8 3
7 8 3
1 2 6
4 2 6
7 2 6
1 5 6
4 5 6
7 5 6
1 8 6
4 8 6
7 8 6
1 2 9
4 2 9
7 2 9
1 5 9
4 5 9
7 5 9
1 8 9
4 8 9
7 8 9
Upvotes: 4