How to take elements of a Matrix and use each one as Input-Variable for the same function? - matlab

I have given a matrix with 485x1 elements. MatLab shall take the first 12 of them and make them a new matrix.
Then I have a variable named C and a function f(C).
MatLab shall take the first element of the new matrix and make it C. Then it shall perform f(C) and save the result as result1.
Then it should take the second element of the new matrix and make it C. Then it shall perform f(C) again and save the result as result2 and so on.
So in the end I need 12 result variables.
How can I program this?

This is question asks for very basic stuff. Like adressing the first 12 elements of a matrix. You might want to consider reading a few FAQs.
However a basic solution can look like this:
M = [1:485]'; %// a 485x1 matrix (vector)
newMatrix = M(1:12); %// newMatrix contains the first 12 elements of M (also vector)
result = cell(1,12); %// result as a cell
f = #(x) x+1; % a function f
for i = 1:12
C = newMatrix(i); % get each value from newMatrix, call it C
result{i} = f(C); % apply f() on c and store the result
end
It is not a good idea to generate variables result1, result2, ..., result12, you can read more about it here. Better use a cell for storing the variables, you can then adress the i-th result as result{i}.

Related

Vectorization of a small code snippet

q=
2
4
6
1
6
8
From=
1
4
2
To=
3
6
3
q is a sequence of points. For instance, q(From(1):To(1)) gives 2,4,6. I want to vectorize this example.
This is non-vectorized working code:
J=3;
L=cell(J,1);
for j=1:J
L{j}=q(From(j):To(j));
end
Its result is:
L=
2,4,6 % j=1
1,6,8 % j=2
4,6 % j=3
I cannot figure out how to get a vectorized form of this code. I tried to convert L into 2-dim array, but anyway nothing works.
You can get rid of the for loop by using arrayfun to apply a specific function on all elements of the inputs. However, I'm not sure if it will be much faster than the loopy version.
The code below produces output equivalent to your original cell array L:
L2 = arrayfun(#(x,y)q(x:y), From, To, 'UniformOutput', false);
Here, #(x,y)q(x:y) defines an anonymous function that returns subvectors from q according to the inputs x and y, which are picked by arrayfun from your input vectors From and To.
As suggested in the comments, if you desire extra genericity you can specify another function handle like this:
L_fun = #(q)arrayfun(#(x,y)q(x:y), From, To, 'uniformoutput', false);
...and then call it for an arbitrary vector (not necessarily your original q) as such:
q2 = rand(10,1); %// Random vector for testing
Lout = L_fun(q2); %// Use From and To to pick from q2
Or even define a handle which takes all inputs:
L_fun = #(q,From,To)arrayfun(#(x,y)q(x:y), From, To, 'uniformoutput', false);
but in this case it might be better to actually write a named function already.

Apply a function to each sub-cell of a cell in Matlab?

I have a cell C in Matlab of dimension mx1, e.g. m=3
C={{1 2 3} {4 5 6} {7 8 9 10}}
Then I have a function g written in a separate m-file
function D=g(C{i},a,b)
...
end
that takes any sub-cell C{i} of C and using some other parameters a and b gives a vector D of dimension fx1.
I want to apply the function g to each sub-cell of C and assemble the obtained fx1 vectors in a matrix fxm without using loops. I have seen the command cellfun but I don't know how to make it working with a function written by myself. Any suggestion?
Simple. First make a handle to the function where the only input is the cell array:
h = #(x) D(x, a, b);
Here, x would be a cell from the cell array. Also, I'm going to assume that a and b are already defined in your workspace. After, just do this:
out = cellfun(h, C, 'uni', 0);
The first argument is a handle to the function, which we've already defined. The next parameter is the cell array you want to operate on and apply the function h to every cell in your array. You need to specify the uni=0 flag because the output is non-uniform. Because your function outputs a vector per cell, this is mandatory. If your function outputted a single value, then this declaration of uni=0 is not required.
Alternatively, you can do this in a loop... which is what cellfun ultimately performs:
out = cell(numel(C), 1);
for idx = 1 : numel(C)
out{idx} = D(C{idx}, a, b);
end
To me, the second option is more suitable for those who aren't used to using cellfun.

MATLAB: How to evaluate a function with multiple inputs on all possible combinations of input vectors

Say I have a simple function with three inputs
f = #(a,b,c) a+b+c
I would like to evaluate this function on combinations of inputs
A = 1:10
B = 2:2:10
C = 0.1:0.1:1
and store the output in a matrix F.
Right now I am doing this as follows:
F = NaN(length(A),length(B),length(C));
for ia = 1:length(A)
for ib = 1:length(B)
for ic = 1:length(C)
F(ia,ib,ic) = f(A(ia),B(ib),C(ic))
end
end
end
I am wondering if there is an efficient way to do this without the use of sloppy for loops, *and without having to vectorize the function f.
If you want neat syntax and don't care much about memory or speed, you can use:
ndgrid to generate all combinations; and then
arrayfun to call f on each combination:
The second step exploits the fact that arrayfun can be called with several arrays as input, and in that case it takes corresponding elements from each array:
[aa, bb, cc] = ndgrid(A,B,C); %// step 1
result = arrayfun(f, aa, bb, cc); %// step 2
As for the memory and speed concerns I mentioned above:
Step 1 requires quite a lot of memory if the input vectors are large, because all combinations are generated at once.
Step 2 may result in code slower than using for loops; see for example here.

How to vectorize this Matlab loop

I need some help to vectorize the following operation since I'm a little confused.
So, I have a m-by-2 matrix A and n-by-1 vector b. I want to create a n-by-1 vector c whose entries should be the values of the second column of A whose line is given by the line where the correspondent value of b would fall...
Not sure if I was clear enough. Anyway, the code below does compute c correctly so you can understand what is my desired output. However, I want to vectorize this function since my real n and m are in the order of many thousands.
Note that values of bare non-integer and not necessarily equal to any of those in the first column of A (these ones could be non-integers too!).
m = 5; n = 10;
A = [(0:m-1)*1.1;rand(1,m)]'
b = (m-1)*rand(n,1)
[bincounts, ind] = histc(b,A(:,1))
for i = 1:n
c(i) = A(ind(i),2);
end
All you need is:
c = A(ind,2);

element by element matrix multiplication in Matlab

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!