Apply a function to each sub-cell of a cell in Matlab? - 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.

Related

Perform a function on each value of a vector in matlab?

I have a vector, a, shape (10000,1) filled with values. I also have vector b, same shape, filled with zeros. I want to take my function, apply it to each value in vector a, return those values into vector b. Below is what I tried, as well as a few variations of this. How can I perform this function on each value of the vector and replace each zero in vector b with what that function returns?
for i=1:length(a)
b(i) = function(a)
end
You can use arrayfun to do this
b = arrayfun(#someFunction, a); % Calls b(i) = someFunction(a(i)) for all elements of a
(Although it's common in MATLAB to try and make someFunction be "vectorised", so that you can instead say simple b = someFunction(a))

Converting a function to cellfun format in MATLAB

I had a matrix A(32x8) for which I wrote the following function
function x = y(A)
x=[A(:,1:2),isnan(A(:,3:5)),A(:,6:end)];
x(sum((x==1),2)>0,:) = [];
end
Now I have an Array B (100x1) where each cell contains the Matrix A(32x8) with different values, So how can I write a function as same as above for all the cell in the array in MATLAB.
I tried following way
Class=cellfun(#(x) x{:,1:2},isnan{x{:,3:5}},x{:,6:end},B, 'UniformOutput', false);
To apply your function y o each element in the cell array B, use cellfun as follows:
cellfun(#y, B, 'UniformOutput', false);
#y is a handle to the function you wrote. It must exist, so that if you write y(B{1}) you get the correct output for the first element in B. cellfun simply applies that function to all elements in the cell array. It is equivalent to writing a loop over B.

MATLAB: return both arguments from ISMEMBER when used inside SPLITAPPLY

How can I access both arguments of ismember when it is used inside splitapply?
slitapply only returns scalar values for each group, so in order to compute nonscalar values for each group (as returned by the first argument of ismemebr), one has to enclose the anonymous function (in this case ismember) inside curly brackets {} to return a cell array.
But now, when I provide two output arguments to splitapply, I get an error:
Output argument "varargout{2}" (and maybe others) not assigned during call to
"#(x,y) {ismember(x,y)}"
ADD 1
I can create another function, say, ismember2cell which would apply ismember and turn outputs into cell arrays:
function [a, b] = ismember2cell(x,y)
[a,b] = ismember(x,y);
a = {a};
b = {b};
end
but maybe there is a solution which doesn't require this workaround.
One potentially faster option is to just do what splitapply is already doing under the hood by splitting your data into cell arrays (using functions like mat2cell or accumarray) and then using cellfun to apply your function across them. Using cellfun will allow you to easily capture multiple outputs (such as from ismember). For example:
% Sample data:
A = [1 2 3 4 5];
B = [1 2 1 5 5];
G = [1 1 1 2 2]; % Group index
% Group data into cell arrays:
cellA = accumarray(G(:), A(:), [], #(x) {x(:).'}); % See note below about (:).' syntax
cellB = accumarray(G(:), B(:), [], #(x) {x(:).'});
% Apply function:
[Lia, Locb] = cellfun(#ismember, cellA, cellB, 'UniformOutput', false);
NOTE: My sample data are row vectors, but I had to use the colon operator to reshape them into column vectors when passing them to accumarray (it wants columns). Once distributed into a cell array, each piece of the vector would still be a column vector, and I simply wanted to keep them as row vectors to match the original sample data. The syntax (:).' is a colon reshaping followed by a nonconjugate transpose, ensuring a row vector as a result no matter the shape of x. In this case I probably could have just used .', but I've gotten into the habit of never assuming what the shape of a variable is.
I cannot find a global solution, but the accepted answer of this post helps me to define a helper function for your problem:
function varargout = out2cell(varargin)
[x{1:nargout}]=feval(varargin{:});
varargout = num2cell(x);
I think that you may succeed in calling
splitapply(#(x,y) out2cell(#ismember, x, y), A, B);

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

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}.

Converting Cell array of function handle into a single array of function handle

I need to build up a vector of non-linear equations to be used in fsolve to solve it. But I should make each element of the vector in each loop iteration. How can I make up such a vector? In fact, I can not use cell array. How can I convert a cell array like {#(x) x(1)+x(2)^2; #(x) x(1)-2*(x(2))} into an array like #(x) [ x(1)+x(2)^2 ; x(1)-2*(x(2))]? Because I want to use fsolve to solve the system of non-linear equations.
Use func2str to get the function definitions in string and use str2func to get the desired function, if A is the cell array containing the function handles:
B = strcat(regexprep(cellfun(#func2str, A, 'uni', 0), '^#\(x\)', ''), ';');
F = str2func(strcat('#(x) [', B{:}, ']'));
Now F contains the desired function handle.
Why convert? Why not use something like
% Your cell array
Fs = {#(x) x(1)+x(2)^2; #(x) x(1)-2*x(2)};
% Just use cellfun
solution = fsolve(#(y) cellfun(#(x) x(y), Fs), [0 0])