the fastest way to replicate a vector in two direction - matlab

I have a vector for which I want to replicate its elements in both row and column directions. I have found that using ones built-in function is faster that m-file functions repmat and kron. I have seen some examples for replicating a vector in one direction, however I could not find how to do it in both direction.
Consider the following example:
a = [1 2 3];
I want to create these matrices:
b = [1 1 1
1 1 1
2 2 2
2 2 2
3 3 3
3 3 3];
and
c = [1 2 3 1 2 3
1 2 3 1 2 3];
How can I do this with ones? It there any faster way?
In my code, the vectors to be replicated are bigger and also I have to do this for many vectors in a for loop. so I am looking for a faster way.
How about if I had a matrix to be replicated? for example:
d = [1 2 3
4 5 6];
and I want to have:
e = [1 2 3 1 2 3
4 5 6 4 5 6
1 2 3 1 2 3
4 5 6 4 5 6];

c and e are straightforward cases for repmat. b is different, the most common suggestion is to use kron(a', ones(2,3)) but here are some alternatives: A similar function to R's rep in Matlab
According to the many answers in that link, the fastest is possibly
reshape(repmat(a, 6, 1), 3, 6)'

You can do it in a simple and ricorsive way:
d = [1 2 3;
4 5 6];
while (!(STOP_CONDITION_OCCURS))
d = [d d; d d];
end;
etc.

Related

Without for loop, can I generate list [1 2 3 2 3 4 3 4 5 ...] in matlab?

Unlike Python, MATLAB list generation expression is limited. In MATLAB I am only allowed to do a:b:c. Can I generate a list [1 2 3 2 3 4 3 4 5 ...] in MATLAB without using for loop?
N = 3;
M = 4;
result = reshape((1:N).'+(0:M-1), 1, []);
gives
result =
1 2 3 2 3 4 3 4 5 4 5 6
How it works
(1:N).'+(0:M-1) uses implicit expansion to create the M×N matrix
1 2 3 ... M
2 3 4 ... M+1
3 4 5 ... M+2
...
N N+1 N+2 ... N+M-1
Then reshape(..., 1, []) reshapes this matrix into a row vector, reading the elements in column-major order (down, then across).
One approach would be to make three lists [1,2,3...], [2,3,4...] and [3,4,5...] and interleave them. Alternatively, you can take advantage of the pattern: [1,2,3,4,5,6,7,8,9]-[0,0,0,2,2,2,4,4,4]=[1,2,3,2,3,4,3,4,5]. The repelem() function is useful for this kind of operation.
You can try cell2mat + arrayfun like belwn
n = 3;
m = 3;
res = cell2mat(arrayfun(#(x) x+(1:n),1:m,'UniformOutput',false));
such that
res =
2 3 4 3 4 5 4 5 6

left cyclic permutation

I want to make left cyclic permutation using MATLAB.
Consider matrix p :
p = [2 3 4 5];
Output :
[2 3 4 5;
3 4 5 2;
4 5 2 3;
5 2 3 4];
I hope the code is available for bigger data. Anyone please help me to make this in code using MATLAB.
A loop free alternative:
[X, Y] = meshgrid(1:numel(p));
p(mod(X+Y-2,numel(p))+1)
This is one approach:
cell2mat(arrayfun(#(n) circshift(p,[0 -n]),0:3,'uni',0).')
ans =
2 3 4 5
3 4 5 2
4 5 2 3
5 2 3 4
Note that arrayfun is really just a loop disguised as a one-liner. Thus explicitly writing out a loop to do the same thing might be equally fast/slow.

what is the meaning of a(b) in matlab ? where a and b are matrix [duplicate]

This question already has answers here:
Got confused with a vector indexed by a matrix, in Matlab
(2 answers)
Closed 8 years ago.
Suppose:
a =
1 2 3
4 5 6
2 3 4
and
b =
1 3 2
6 4 8
In MATLABa(b) gives:
>> a(b)
ans =
1 2 4
3 2 6
What is the reason for this output?
when you have a matrix a:
a =
1 2 3
4 5 6
7 8 9
and b:
b =
1 3 4
3 2 6
then a(b) is a way of adressing items in a and gives you:
>> a(b)
ans =
1 7 2
7 4 8
to understand this you have to think of a als a single column vector
>> a(:)
ans =
1
4
7
2
5
8
3
6
9
now the first row of b (1 3 4) addresses elements in this vector so the first, the 3rd and the forth element of that single column vector which are 1 7 and 2 are adressed. Next the secound row of b is used as adresses for a secound line in the output so the 3rd, the 2nd and the 6th elements are taken from a, those are 7 4 and 8.
It's just a kind of matrix indexing.
Matrix indexes numeration in 'a' matrix is:
1 4 7
2 5 8
3 6 9
This is a possible duplicate to this post where I gave an answer: Got confused with a vector indexed by a matrix, in Matlab
However, I would like to duplicate my answer here as I think it is informative.
That's a very standard MATLAB operation that you're doing. When you have a vector or a matrix, you can provide another vector or matrix in order to access specific values. Accessing values in MATLAB is not just limited to single indices (i.e. A(1), A(2) and so on).
For example, let's say we had a vector a = [1 2 3 4]. Let's also say we had b as a matrix such that it was b = [1 2 3; 1 2 3; 1 2 3]. By doing a(b) to access the vector, what you are essentially doing is a lookup. The output is basically the same size as b, and you are creating a matrix where there are 3 rows, and each element accesses the first, second and third element. Not only can you do this for a vector, but you can do this for a matrix as well.
Bear in mind that when you're doing this for a matrix, you access the elements in column major format. For example, supposing we had this matrix:
A = [1 2
3 4
5 6
7 8]
A(1) would be 1, A(2) would be 3, A(3) would be 5 and so on. You would start with the first column, and increasing indices will traverse down the first column. Once you hit the 5th index, it skips over to the next column. So A(5) would be 2, A(6) would be 4 and so on.
Here are some examples to further your understanding. Let's define a matrix A such that:
A = [5 1 3
7 8 0
4 6 2]
Here is some MATLAB code to strengthen your understanding for this kind of indexing:
A = [5 1 3; 7 8 0; 4 6 2]; % 3 x 3 matrix
B = [1 2 3 4];
C = A(B); % C should give [5 7 4 1]
D = [5 6 7; 1 2 3; 4 5 6];
E = A(D); % E should give [8 6 3; 5 7 4; 1 8 6]
F = [9 8; 7 6; 1 2];
G = A(F); % G should give [2 0; 3 6; 5 7]
As such, the output when you access elements this way is whatever the size of the vector or matrix that you specify as the argument.
In order to be complete, let's do this for a vector:
V = [-1 9 7 3 0 5]; % A 6 x 1 vector
B = [1 2 3 4];
C = V(B); % C should give [-1 9 7 3]
D = [1 3 5 2];
E = V(D); % E should give [-1 7 0 9]
F = [1 2; 4 5; 6 3];
G = V(F); % G should give [-1 9; 3 0; 5 7]
NB: You have to make sure that you are not providing indexes that would make the accessing out of bounds. For example if you tried to specify the index of 5 in your example, it would give you an error. Also, if you tried anything bigger than 9 in my example, it would also give you an error. There are 9 elements in that 3 x 3 matrix, so specifying a column major index of anything bigger than 9 will give you an out of bounds error.

Construct columns from submatrices in Matlab

In Matlab, I'm trying to transform a matrix A to another matrix B such that B's columns are made up of square submatrices of A. For example, if A is:
A = [1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4];
I'd like B to be:
B = [1 2 3 4
1 2 3 4
1 2 3 4
1 2 3 4]
A could be, say 16-by-16, and constructing B from 4-by-4 squares would result in B being 4-by-64.
Is there an efficient way to do this using reshape in combination with some other commands? Or some other approach? I am currently iterating in a loop, which is very slow with a large number of large source matrices.
Assume your matrix is a bit more general, and made of 3x2 blocks:
A = [1 1 2 2
1 1 2 2
1 1 2 2
3 3 4 4
3 3 4 4
3 3 4 4
5 5 6 6
5 5 6 6
5 5 6 6];
b = [3 2];
szA = size(A);
Transpose, reshape, permute, reshape.
nb = prod(szA./b); % Number of blocks
nelb = prod(b); % Number of elements per block
out1 = reshape(permute(reshape(A',szA(2),b(1),szA(1)/b(1)),[2,1,3]),nelb,nb)
Alternatively, slower and memory intensive but more readable:
d1 = repmat(b(1),1,szA(1)/b(1));
d2 = repmat(b(2),1,szA(2)/b(2));
out = reshape(mat2cell(A,d1,d2)',1,nelb);
out = reshape([out{:}],nelb,nb)
Now, if the blocks are square, simply set b = [2,2] or b = [3,3], etc..., or simplify the general formulation removing indexing of b and prod.

MATLAB Concatenate vectors with unequal dimensions

Lets say I have got vector1:
2
3
5
6
7
9
And a vector2:
1
2
3
Now I would like to obtain the following matrix:
2 1
3 2
5 3
6 1
7 2
9 3
That is, I want to add vector2 as a column next to vector1 until the new column is completely filled. I have to do this with a lot of vectors with different sizes. The only thing I know in advance is that the length of vector1 is an integer multiple of the length of vector2.
Any suggestions?
Use repmat to replicate the smaller matrix.
a = [2 3 5 6 7 9]';
b = [1 2 3]';
c = [a repmat(b, length(a) / length(b), 1)]
Result:
c =
2 1
3 2
5 3
6 1
7 2
9 3
You can then replicate the vector:
[vector1, repmat(vector2,n,1)]
where n is your multiple of vector2.
This could be an alternative
[x [y'; y']]