How to vectorize the following code in Matlab?
m = meshgrid(1:n);
for i = 1:n
for j = 1:n
m(i,j) = max(i,j);
end
end
Another way to think of the question would be: how to implement the Mathematica command:
Table[Max[i,j],{i,1,n},{j,1,n}]:
in Matlab.
With implicit expansion,
m = max([1:n].',[1:n]);
For n = 5:
m =
1 2 3 4 5
2 2 3 4 5
3 3 3 4 5
4 4 4 4 5
5 5 5 5 5
Related
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
I have genearalised the outer product between a 3vector and itself to take input from a collection (NxNx3 matrix) of 3-vectors.
At the moment, my function does what I want (see example output and input below), and it looks like this. I would like to make it faster by avoiding the two for loops which I currently use.
function [rr]=OuterVec(r)
N = size(r,1);
rr = zeros(N,N,3,3);
for i=1:N
for j=1:N
rr(i,j,:,:)=kron(reshape(r(i,j,:),[1,3]),permute(r(i,j,:),[3 2 1]));
end
end
end
I/O Examples
c = ones(2,2);
V(1,1,:)=[1 2 3];
u = c.*V;
OuterVec(u)
ans(:,:,1,1) =
1 1
1 1
ans(:,:,2,1) =
2 2
2 2
ans(:,:,3,1) =
3 3
3 3
ans(:,:,1,2) =
2 2
2 2
ans(:,:,2,2) =
4 4
4 4
ans(:,:,3,2) =
6 6
6 6
ans(:,:,1,3) =
3 3
3 3
ans(:,:,2,3) =
6 6
6 6
ans(:,:,3,3) =
9 9
9 9
You only need to permute dimensions and apply element-wise product with singleton expansion:
rr = bsxfun(#times, r, permute(r, [1 2 4 3]));
Or, in Matlab R2016b onwards,
rr = r .* permute(r, [1 2 4 3]);
How can I generate the following matrix having m rows and n columns?
1st row 1 2 3 L n-1 n
2nd 2 3 4 L n 1
3rd 3 4 5 n-1 1 2
Nth M M M ....
N-1 m-1 m m+1 L m-3 m-2
last m m+1 m+2 l m-2 m-1
It's difficult to tell from your description, but it appears you want to create a matrix where the first row is 1:n and each successive row is a circular shift to the left of the previous row. If so, you can still use hankel for this (as Dev-iL mentions in their answer), but incorporate a remainder operation like so:
n = 5;
m = 8;
mat = rem(hankel(0:(m-1), (m-1):(m+n-2)), n)+1
mat =
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
4 5 1 2 3
5 1 2 3 4
1 2 3 4 5
2 3 4 5 1
3 4 5 1 2
This looks like a Hankel matrix. You should use the 2-input syntax for it,
H = hankel(c,r)
So for example, with m = 4 and n = 5 we get:
m = 4; n = 5;
X = hankel( 1:m, m:m+n-1 )
X =
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
4 5 6 7 8
How to effectively vectorize the following MATLAB code, which performs permutation of each row of matrix R by indices in corresponding row of matrix P?
for i = 1:size(P,1)
pP(i,:) = R(i,P(i,:));
end
example:
P = [3 2 1;
3 1 2;
2 3 1;
2 1 3;
1 2 3;
1 3 2]
R = [6 5 4;
6 4 5;
5 6 4;
5 4 6;
4 5 6;
4 6 5]
produce following matrix pR:
4 5 6
5 6 4
6 4 5
4 5 6
4 5 6
4 5 6
One approach with bsxfun -
nrows = size(R,1)
pP = R(bsxfun(#plus,[1:nrows]',(P-1)*nrows))
Or with ndgrid -
[m,n] = size(R)
pP = R(sub2ind([m n],ndgrid(1:m,1:n),P))
Or replace ndgrid(1:m,1:n) with repmat: repmat([1:m]',[1 n]) or with meshgrid:meshgrid(1:m,1:n).'.
This might not be the best way to do it, but you could do something like:
IND1 = P(:,1)
Q(:,1) = diag(R(:,IND));
and repeat for P(:,2), P(:,3) in a similar fashion.
You can use arrayfun to avoid the loop but probably won't gain in performance if that it is the reason for vectorizing it:
cell2mat(arrayfun(#(k) R(k, P(k,:)), (1:size(P,1)).', 'uni', 0))
This is the input matrix
7 9 6
8 7 9
7 6 7
Based on the frequency their appearance in the matrix (Note. these values are for explanation purpose. I didn't pre-calculate them in advance. That why I ask this question)
number frequency
6 2
7 4
8 1
9 2
and the output I expect is
4 2 2
1 4 2
4 2 4
Is there a simple way to do this?
Here's a three-line solution. First prepare the input:
X = [7 9 6;8 7 9;7 6 7];
Now do:
[a m n] = unique(X);
b = hist(X(:),a);
c = reshape(b(n),size(X));
Which gives this value for c:
4 2 2
1 4 2
4 2 4
If you also wanted the frequency matrix, you can get it with this code:
[a b']
Here is a code with for-loop (a is input matrix, freq - frequency matrix with 2 columns):
weight = zeros(size(a));
for k = 1:size(freq,1)
weight(a==freq(k,1)) = freq(k,2);
end
Maybe it can be solved without loops, but my code looks like:
M = [7 9 6 ;
8 7 9 ;
7 6 7 ;];
number = unique(M(:));
frequency = hist(M(:), number)';
map = containers.Map(number, frequency);
[height width] = size(M);
result = zeros(height, width); %allocate place
for i=1:height
for j=1:width
result(i,j) = map(M(i,j));
end
end