I have a 7x21 matrix called A. Within this matrix there are three equally sized 7x7 submatrices. I call them B,C and D, where B = A(:,1:7), C = A(:,8:14) and D = A(:,15:21).
How can I produce a matrix E which is also 7x7 matrix where simply B, C and D are added up, i.e. E = B+C+D.
Thanks a lot for your help!
Generic code to get such an output -
N = 3; %// Number of submatrices
[m,n] = size(A) %// Get size [no. of cols must be multiple of N
E = reshape(sum(reshape(A,m*n/N,[]),2),m,n/N)
I don't see what's going to be more straightforward and concise than
E = A(:,1:7) + A(:,8:14) + A(:,15:21)
Unless you need an expression that generalizes in some way you're not describing...
Related
Suppose I have a matrix a = [1,2,3;4,1,2;3,4,2].
I need to create a logical matrix which is 1 wherever there is an element of b in a. The equivalent of a==4 | a==1 if my array b is a small one like [1,4].
I know one way to do this is:
b = [1,4];
c = logical(zeros(size(a)));
for i=b
c = c | a==i;
end
This solution may not scale well if a and b are large. Is there a cleaner way to do it for larger arrays?
I was hoping a == b would give me what i wanted, but it doesn't.
You can use ismember to output a logical array which is true whenever an element of the first input is a member of the second input. The output is the same size as the first input.
c = ismember( a, b );
In your example:
a = [1,2,3;
4,1,2;
3,4,2];
b = [1,4];
c = ismember( a, b );
% >> c =
% [1,0,0;
% 1,1,0;
% 0,1,0]
So I have the following matrices:
A = [1 2 3; 4 5 6];
B = [0.5 2 3];
I'm writing a function in MATLAB that will allow me to multiply a vector and a matrix by element as long as the number of elements in the vector matches the number of columns. In A there are 3 columns:
1 2 3
4 5 6
B also has 3 elements so this should work. I'm trying to produce the following output based on A and B:
0.5 4 9
2 10 18
My code is below. Does anyone know what I'm doing wrong?
function C = lab11(mat, vec)
C = zeros(2,3);
[a, b] = size(mat);
[c, d] = size(vec);
for i = 1:a
for k = 1:b
for j = 1
C(i,k) = C(i,k) + A(i,j) * B(j,k);
end
end
end
end
MATLAB already has functionality to do this in the bsxfun function. bsxfun will take two matrices and duplicate singleton dimensions until the matrices are the same size, then perform a binary operation on the two matrices. So, for your example, you would simply do the following:
C = bsxfun(#times,mat,vec);
Referencing MrAzzaman, bsxfun is the way to go with this. However, judging from your function name, this looks like it's homework, and so let's stick with what you have originally. As such, you need to only write two for loops. You would use the second for loop to index into both the vector and the columns of the matrix at the same time. The outer most for loop would access the rows of the matrix. In addition, you are referencing A and B, which are variables that don't exist in your code. You are also initializing the output matrix C to be 2 x 3 always. You want this to be the same size as mat. I also removed your checking of the length of the vector because you weren't doing anything with the result.
As such:
function C = lab11(mat, vec)
[a, b] = size(mat);
C = zeros(a,b);
for i = 1:a
for k = 1:b
C(i,k) = mat(i,k) * vec(k);
end
end
end
Take special note at what I did. The outer-most for loop accesses the rows of mat, while the inner-most loop accesses the columns of mat as well as the elements of vec. Bear in mind that the number of columns of mat need to be the same as the number of elements in vec. You should probably check for this in your code.
If you don't like using the bsxfun approach, one alternative is to take the vector vec and make a matrix out of this that is the same size as mat by stacking the vector vec on top of itself for as many times as we have rows in mat. After this, you can do element-by-element multiplication. You can do this stacking by using repmat which repeats a vector or matrices a given number of times in any dimension(s) you want. As such, your function would be simplified to:
function C = lab11(mat, vec)
rows = size(mat, 1);
vec_mat = repmat(vec, rows, 1);
C = mat .* vec_mat;
end
However, I would personally go with the bsxfun route. bsxfun basically does what the repmat paradigm does under the hood. Internally, it ensures that both of your inputs have the same size. If it doesn't, it replicates the smaller array / matrix until it is the same size as the larger array / matrix, then applies an element-by-element operation to the corresponding elements in both variables. bsxfun stands for Binary Singleton EXpansion FUNction, which is a fancy way of saying exactly what I just talked about.
Therefore, your function is further simplified to:
function C = lab11(mat, vec)
C = bsxfun(#times, mat, vec);
end
Good luck!
I have n groups, each group has m vectors of dimension d. These are represented by a d*m*n matrix A.
I have n vectors of dimension d, represented by a d*n matrix B.
Now I would like to subtract all the m vectors in the group i by the corresponding vector i in B (and I do that for all i = 1,...,n).
This can be done simply like:
C = zeros(size(A));
for i = 1:n
for j = 1:m
C(:,j,i) = A(:,j,i) - B(:,i);
end
end
However, this is quite slow because of the loop. Could anybody please suggest me a very fast way to do that?
Thank you in advance for your help.
Perfect case for bsxfun -
C = bsxfun(#minus,A,permute(B,[1 3 2]))
Give this a shot:
B = repmat(reshape(B,[d 1 n]),[1 m 1]);
C = A - B;
EDIT
Divakar's solution is faster. For 100 runs with d=50;m=75;n=100; the average times were as follows:
Nesbit's - .0165s
Divakar's - .0013s
Mine - .0023s
I have a matrix K of dimensions n x n. I want to create a new block diagonal matrix M of dimensions N x N, such that it contains d blocks of matrix K as its diagonal.
I would have directly used M = blkdiag(K,K,K) etc. had d been smaller. Unfortunately, d is very large and I don't want to manually write the formula with d exactly same arguments for the blkdiag() function.
Is there any shorter, smarter way to do this?
you can use kron for that.
M = kron(X,Y)
returns the Kronecker tensor product of X and Y. The result is a large array formed by taking all possible products between the elements of X and those of Y. If X is m-by-n and Y is p-by-q, then kron(X,Y) is m*p-by-n*q. So in your case something like this will do:
M = kron(eye(L),K)
with L the # of blocks.
tmp = repmat({K},d,1);
M = blkdiag(tmp{:});
You should never use eval, or go into for loops unnecessarily.
Kron is a very elegant way.
Just wanted to share this as it also works.
The following should work:
d=5; K=eye(3); T = cell(1,d);
for j=1:d
T{j} =K;
end
M = blkdiag(T{:})
s = 'A,';
s = repmat(s,[1,n2]);
s = ['B=blkdiag(', s(1:end-1),');'];
eval(s);
It can be faster than using kron-eye.
A "for" loop may might help. Like:
M = k;
for i=1:N/n - 1
M=blkdiag(M,k);
end
If I have 2 vectors: A with n elements and B with m elements and m < n,
how do I identify all the elements in A which are in B, without using a for loop?
Many thanks
C = intersect(A,B) will give you all the elements which are in both.
There's also ismember(A,B), which will return a logical array indicating for each member of A whether it is also a member of B.
Here is one solution to find which elements of the longer vector (x) are in the shorter vector (y)
x = 1:10;
y = 2:4;
xrep = repmat(x,length(y),1)
yrep = repmat(y',1,length(x))
idx = any(xrep==yrep)