getting all possibilities from 2 matrix - matlab

I'm trying to get all possible outcome from 2 different dimension matrix.
say,
A=[1 2 3 4;2 3 4 5]
and
B=[11 12; 13 14; 15 16]
with the output of
C=[1 2 3 4 11 12; 1 2 3 4 13 14; 1 2 3 4 15 16; 2 3 4 5 11 12; 2 3 4 5 13 14; 2 3 4 5 15 16]
I have tried using for loop method but I find it very inefficient and would therefore like to have a better approach to it.
Thanks.

If the repetition of matrix A is always a the number of rows of matrix B and repetition of matrix B is always the number of rows of A. Then, you can use the functions kron and repmat to achieve what you wanted. So, in this example, C can be obtained with a single line as
[kron(A, ones(size(B, 1), 1)) repmat(B, [size(A, 1) 1])]

You can use indexing to achieve this by
C=[A(repmat(1:size(A,1), 1, size(B,1)), :) B(repmat(1:size(B,1), 1, size(A,1)), :)];
A more readable version is
[X,Y]=meshgrid(1:size(A,1), 1:size(B,1));
C=[A(X(:),:) B(Y(:),:)];

Related

Matlab : How to make label output from interval data?

So i have this data:
A=
2
4
8
9
4
6
1
3
And 3 interval
B=
1 4
5 8
9 12
How to make an output like this
Output=
1
1
2
3
1
2
1
1
The output is based on the interval
you can solve it in several ways. for example, with arrayfun:
A = [2 4 8 9 4 6 1 3].';
B = [1 4;
5 8;
9 12];
res = arrayfun(#(x) find((x >= B(:,1)) & (x <= B(:,2))),A);
If the interval always has the same length, as in your case 4, you can solve it as follows:
Output=ceil(A/4);
If it is not the case, and if not all numbers necessarily fall between any of the intervals, you can compute it as follows. A zero is outputted if a number does not fall within any of the intervals.
% example entry
A=[2 3 4 8 9 4 6 1 3]';
B=[1 4;5 7;9 12]';
Arep=A(:,ones(size(B,2),1)); % replicate array (alternatively use repmat)
Alog=Arep>=B(1,:)&Arep<=B(2,:); % conditional statements, make logical array
Output=Alog*(1:size(B,2))'; % matrix product with natural array to obtain indices

Matlab multiply each row in matrix by different number

Say that I have a matrix:
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
Is there a way to multiply :
row 1 by 1
row 2 by 2
row 3 by 3
and so on?
I am able to do this with for loops, however it if for an assignment where they want us to use matrices.
In the actual assignment A is filled with random number but each row which by multiplied consecutively.
Thanks, any help is much appreciated
You just need to multiply a diagonal matrix by A like so.
A = [ 1 2 3 ; 4 5 6 ; 7 8 9 ; 10 11 12];
disp(diag([1 2 3 4]) * A);
1 2 3
8 10 12
21 24 27
40 44 48
You can use bsxfun to accomplish this easily and very quickly
out = bsxfun(#times, [1 2 3 4].', A)
In newer versions of MATLAB (R2016b and newer) you can actually replace bsxfun with simply *
out = [1 2 3 4].' * A;

How do I extract the odd and even rows of my matrix into two separate matrices in scilab?

I'm very new to scilab syntax and can't seem to find a way to extract the even and odd elements of a matrix into two separate matrix, suppose there's a matrix a:
a=[1,2,3,4,5,6,7,8,9]
How do I make two other matrix b and c which will be like
b=[2 4 6 8] and c=[1 3 5 7 9]
You can separate the matrix by calling row and column indices:
a=[1,2,3,4,5,6,7,8,9];
b=a(2:2:end);
c=a(1:2:end);
[2:2:end] means [2,4,6,...length(a)] and [1:2:end]=[1,3,5,...length(a)]. So you can use this tip for every matrix for example if you have a matrix a=[5,4,3,2,1] and you want to obtain the first three elements:
a=[5,4,3,2,1];
b=a(1:1:3)
b=
1 2 3
% OR YOU CAN USE
b=a(1:3)
If you need elements 3 to 5:
a=[5,4,3,2,1];
b=a(3:5)
b=
3 2 1
if you want to elements 5 to 1, i.e. in reverse:
a=[5,4,3,2,1];
b=a(5:-1:1);
b=
1 2 3 4 5
a=[1,2,3,4,5,6,7,8,9];
b = a(mod(a,2)==0);
c = a(mod(a,2)==1);
b =
2 4 6 8
c =
1 3 5 7 9
Use mod to check whether the number is divisible by 2 or not (i.e. is it even) and use that as a logical index into a.
The title is about selecting rows of a matrix, while the body of the question is about elements of a vector ...
With Scilab, for rows just do
a = [1,2,3 ; 4,5,6 ; 7,8,9];
odd = a(1:2:$, :);
even = a(2:2:$, :);
Example:
--> a = [
5 4 6
3 6 5
3 5 4
7 0 7
8 7 2 ];
--> a(1:2:$, :)
ans =
5 4 6
3 5 4
8 7 2
--> a(2:2:$, :)
ans =
3 6 5
7 0 7

matlab: dividing vector into overlapping chunks of fixed size

I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.

Find multiple row and column combinations in a matrix in Matlab

I have the following matrix:
>> MatrixA = [1 2 3 4; 5 6 7 8; 9 10 11 12; 13 14 15 16]
MatrixA =
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
I want to find the following:
for row 1, I want the 2nd column
for row 2, I want the 3rd column
for row 3, I want the 4th column
for row 4, I want the 4th column
Currently I accomplish this with the following line:
>>diag(MatrixA([1 2 3 4], [2 3 4 4]))
ans =
2
7
12
16
Is there a more direct way to do this (without using diag)?
Well you could use sub2ind, it might be more intuitive. I don't think there is much benefit though, maybe it's more readable:
ind = sub2ind(size(MatrixA), [1 2 3 4], [2 3 4 4])
MatrixA(ind)