Here is the simplified version of the problem I have. Suppose I have a vector
p=[1 5 10]
and another one
q=[.75 .85 .95]
And I want to come up with the following matrix:
res=[1, .75;
1, .85;
1, .95;
5, .75;
5, .85;
5, .95;
10, .75;
10, .85;
10, .95]
This is also known as the Cartesian Product. How can I do that?
CARTPROD Cartesian product of multiple sets. (The cartesian product of multiple input sets is a larger set containing every ordered combination of the input set elements. See example below.) X = CARTPROD(A,B,C,...) returns the cartesian product of the sets A,B,C, etc, where A,B,C, are numerical vectors.
In mathematics, the Cartesian Product of sets A and B is defined as the set of all ordered pairs (x, y) such that x belongs to A and y belongs to B. For example, if A = {1, 2} and B = {3, 4, 5}, then the Cartesian Product of A and B is {(1, 3), (1, 4), (1, 5), (2, 3), (2, 4), (2, 5)}.
Most computers display images as a raster of points called pixels that can be addressed by their coordinates. These coordinates are ordered pairs and hence elements of a Cartesian product.
B = prod( A ) returns the product of the array elements of A . If A is a vector, then prod(A) returns the product of the elements. If A is a nonempty matrix, then prod(A) treats the columns of A as vectors and returns a row vector of the products of each column.
Here's one way:
[X,Y] = meshgrid(p,q);
result = [X(:) Y(:)];
The output is:
result =
1.0000 0.7500
1.0000 0.8500
1.0000 0.9500
5.0000 0.7500
5.0000 0.8500
5.0000 0.9500
10.0000 0.7500
10.0000 0.8500
10.0000 0.9500
A similar approach as the one described by @nibot can be found in matlab central file-exchange.
It generalizes the solution to any number of input sets. This would be a simplified version of the code:
function C = cartesian(varargin)
args = varargin;
n = nargin;
[F{1:n}] = ndgrid(args{:});
for i=n:-1:1
G(:,i) = F{i}(:);
end
C = unique(G , 'rows');
end
For instance:
cartesian(['c','d','e'],[1,2],[50,70])
ans =
99 1 50
99 1 70
99 2 50
99 2 70
100 1 50
100 1 70
100 2 50
100 2 70
101 1 50
101 1 70
101 2 50
101 2 70
Here's a function, cartesian_product
, that can handle any type of input, including string arrays, and returns a table with column names that match the names of the input variables. Inputs that are not variables are given names like var1
, var2
, etc.
function tbl = cartesian_product(varargin)
names = arrayfun(@inputname, 1:nargin, 'UniformOutput', false);
for i = 1:nargin
if isempty(names{i})
names{i} = ['var' num2str(i)];
end
end
rev_args = flip(varargin);
[A{1:nargin}] = ndgrid(rev_args{:});
B = cellfun(@(x) x(:), A, 'UniformOutput', false);
C = flip(B);
tbl = table(C{:}, 'VariableNames', names);
end
>> x = ["a" "b"];
>> y = 1:3;
>> z = 4:5;
>> cartesian_product(x, y, z)
ans =
12×3 table
x y z
___ _ _
"a" 1 4
"a" 1 5
"a" 2 4
"a" 2 5
"a" 3 4
"a" 3 5
"b" 1 4
"b" 1 5
"b" 2 4
"b" 2 5
"b" 3 4
"b" 3 5
>> cartesian_product(1:2, 3:4)
ans =
4×2 table
var1 var2
____ ____
1 3
1 4
2 3
2 4
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With