How to "project out" some dimensions of an n-d array? - matlab

Suppose that M is an n-dimensional array (of numbers). one can also think of M as an (n - k)-dimensional array of k-dimensional arrays. I want to generate the array corresponding to applying some function f to each one of those k-dimensional arrays.
More precisely, I want to generate a new (n - k)-dimensional array N where the value for each cell N(i1, i2, …, in-k-1, in-k) is obtained by applying a (scalar-valued) function f to the k-dimensional array at M(i1, i2, …, in-k-1, in-k).
(The function f is typically some "summarizing function", like the mean, the median, the max, or the min.)
I imagine that the way to do this would involve arrayfun in some way, but I have not been able to figure out how to get arrayfun to iterate only over the first (n - k) dimensions of M.

If you are only interested in applying simple functions like mean / median / max / min to the k-vectors, i.e. functions for which the k-dimensional structure of these vectors is irrelevant, then this is the way to go:
s = size(M);
N = reshape(fun(reshape(M, prod(s(1 : end - k)), []).'), s(1 : end - k));
This code assumes that fun operates on the first dimension of its argument, as is the case for mean, median, min, and max and many other Matlab standard functions.
It first reshapes M into a two-dimensional array, where the first dimension corresponds to the first n – k dimensions of M, and the second dimension corresponds to the last k dimensions of M. Through the transpose fun operates across the second set of dimensions. It returns a scalar for each column, such that the result can be reshaped back into an (n – k)-dimensional array N of a form corresponding to the first n – k dimensions of M.

Related

Indexing 3d matrix with 2d Matrix plus vector

I have a m * n * k Matrix called M which I want to index to get the mean of some Data.
I have a logical m * n matrix called EZG and want to apply this on every of the k-th dimension from 1:(end-1) (call this vector V).
Any chance to write it without a loop like this:
M=rand(3,3,3)
EZG=logical([1,1,1;0,1,0;0,0,1])
V=1:size(M,3)-1
mean(mean(M(EZG,V)1),2)
Result should be a onedimensional vector of the length of V.
Thank you
I think this is what you want:
M=rand(3,3,3);
EZG=logical([1,1,1;0,1,0;0,0,1]);
% repeat EZG K-1 times, and add zeros to the Kth slice
V=cat(3,repmat(EZG,1,1,size(M,3)-1),false(size(M,1),size(M,2)));
% logical index and mean
m=mean(M(V));

matlab - ith element of vector is the sum of the first i elements of a different vector

I'm trying to compute a vector A for which the ith element is the sum of the first i elements of a different vector B (this vector is given).
I couldn't work out how to do this and the internet wasn't much help either.
I am very new to matlab so an easy solution would be preferred :)
Use MATLAB's cumsum function.
code example:
%generates random vector b
b = rand(5,1);
%calculates accomulative sum
a = cumsum(b);
Result:
b = [0.4319 0.9616 0.5671 0.8731 0.5730]
a = [0.4319 1.3935 1.9606 2.8338 3.4068]

How can I generalize this function to `n` terms?

I'd like to create a function that adds several gaussian terms of various width over some specified region:
G(a,b,x) = a_1 exp(- b_1 x^2) + a_2 exp(- b_2 x^2) + ... a_N exp(-b_N x^2)
I'd like this function to output an array of length x, summing over the terms of parameters a,b provided, something like:
x = linspace(-2,2,1000);
N_gauss = #(a,b) a(:).*exp(-b(:)*x.^2);
This example actually works if a,b have only a single value, but when they become vectors it no longer works (I suppose Matlab doesn't know what should be added, multiplied or remain a vector). Is this even possible?
You can do this purely by matrix multiplication. Let's tackle the problem slowly and work our way up. You first need to form products of the elements of the vector b and scalar values stored in x. First create a 2D matrix of values where each row corresponds to the product-wise values between an element in b and an element in x. The element (i,j) in this matrix corresponds to the product of the ith element in x with the jth element in b.
You can achieve this by using the outer product. Make x a column vector and b a row vector, then perform the multiplication. Also, make sure you square each of the x terms as seen in your equation.
term1 = (x(:).^2)*b(:).';
Now you can apply the exponential operator and ensure you place a negative in the exponent so you can build the right side of each term (i.e. exp(- b_i x^2)):
term2 = exp(-term1);
The last thing you need to do is multiply each of the values in the 2D matrix with the right coefficient from the a vector. You can do this by enforcing that a be a column vector and performing matrix-vector multiplication.
out = term2*a(:);
Matrix-vector multiplication is the dot product between the column vector a with each row in the 2D matrix we created before. This exactly corresponds to the summation of your equation for each value in x. As such, this achieves the Gaussian summation for each value in x and places this into a n x 1 vector where n is the total number of elements in x. Putting this all together gives us:
out = exp(-(x(:).^2)*b(:).')*a(:);
To finally abstract this into an anonymous function, do:
N_gauss = #(a,b,x) exp(-(x(:).^2)*b(:).')*a(:);
This function takes in the vectors a, b and x as per your problem.

Find the minimum difference between any pair of elements between two vectors

Which of the following statements will find the minimum difference between any pair of elements (a,b) where a is from the vector A and b is from the vector B.
A. [X,Y] = meshgrid(A,B);
min(abs(X-Y))
B. [X,Y] = meshgrid(A,B);
min(abs(min(Y-X)))
C. min(abs(A-B))
D. [X,Y] = meshgrid(A,B);
min(min(abs(X-Y)))
Can someone please explain to me?
By saying "minimum difference between any pair of elements(a,b)", I presume you mean that you are treating A and B as sets and you intend to find the absolute difference in any possible pair of elements from these two sets. So in this case you should use your option D
[X,Y] = meshgrid(A,B);
min(min(abs(X-Y)))
Explanation: Meshgrid turns a pair of 1-D vectors into 2-D grids. This link can explain what I mean to say:
http://www.mathworks.com/help/matlab/ref/meshgrid.html?s_tid=gn_loc_drop
Hence (X-Y) will give the difference in all possible pairs (a,b) such that a belongs to A and b belongs to B. Note that this will be a 2-D matrix.
abs(X-Y) would return the absolute values of all elements in this matrix (the absolute difference in each pair).
To find the smallest element in this matrix you will have to use min(min(abs(X-Y))). This is because if Z is a matrix, min(Z) treats the columns of Z as vectors, returning a row vector containing the minimum element from each column. So a single min command will give a row vector with each element being the min of the elements of that column. Using min for a second time returns the min of this row vector. This would be the smallest element in the entire matrix.
This can help:
http://www.mathworks.com/help/matlab/ref/min.html?searchHighlight=min
Options C is correct if you treat A and B as vectors and not sets. In this case you won't be considering all possible pairs. You'll end up finding the minimum of (a-b) where a,b are both in the same position in their corresponding vectors (pair-wise difference).
D. [X,Y] = meshgrid(A,B);
min(min(abs(X-Y)))
meshgrid will generate two grids - X and Y - from the vectors, which are arranged so that X-Y will generate all combinations of ax-bx where ax is in a and bx is in b.
The rest of the expression just gets the minimum absolute value from the array resulting from the subtraction, which is the value you want.
CORRECT ANSWER IS D
Let m = size(A) and n = size(B)
You want to subtract each pair of (a,b) such that a is from vector A and b is from vector B.
meshgrid(A,B) creates two matrices X Y both of size nxm where X have rows sames have vector A while Yhas columns same as vector B .
Hence , Z = X-Y will give you a matrix with n*m values corresponding to the difference between each pair of values taken from A and B . Now all you have to do is to find the absolute minimum among all values of Z.
You can do that by
req_min = min(min(abs(z)))
The whole code is
[X Y ] = meshgrid(A,B);
Z= X-Y;
Z = abs(Z);
req_min = min(min(Z));
You could also use bsxfun instead of meshgrid:
min(min(abs(bsxfun(#minus, A(:), B(:).'))))
Or use pdist2:
min(min(pdist2(A(:),B(:))))

Matlab: What is a neutral element in the mean() function?

I have a bunch of values in a 3-dimensional matrix, and I am finding the mean value of them:
mean(mean(mat))
Now, of different reasons I have to append some rows and elements to the matrix. But I want the mean value to stay the same - as if the added elements are neutral and do not inflict in the result.
Like when you multiply a bunch of values, you can multiply additional 1's without changing the result. And with addition you can add further 0's with no inflict.
What kind of value in Matlab can I assign to the new elements in the matrix to make the elements neutral when using the mean()?
Note added
The point is, when I am calculating the mean value I only have the new resized matrix to do it from. Therefore the added elements must be neutral.
I am thinking of something like NaN, but I had no luck with that since the mean value then also end up as NaN.
Adding values equal to the mean of the matrix without the added values will leave the new mean the same. (I hope that makes sense!). Point is to fill in and not change the new mean, use the current mean.
Alternatively, you can fill in with NaN and use the nanmean function.
Add zeros to the matrix and rescale your mean to be the correct value.
i.e. if your original matrix A is n x m and you resize to B which is N x M then :
mean(mean(A)) = sum(sum(A)) / n x m
mean(mean(B)) = sum(sum(B)) / N x M
= sum(sum(A)) / N x M --- since we padded with zeros
Rearranging gives
mean(mean(A)) = mean(mean(B)) * ( ( N x M )/(n x m) )