MATLAB: Using second output of a function in a inline function [duplicate] - matlab

Say I want to create an anonymous function from a m-file-function that returns two outputs. Is it possible to set up the anonymous function such that it only returns the second output from the m-file-function?
Example: ttest2 returns two outputs, t/f and a probability. If I want to use the t-test with cellfun, I might only be interested in collecting the probabilities, i.e. I'd like to write something like this
probabilities = cellfun(#(u,v)ttest2(u,v)%take only second output%,cellArray1,cellArray2)

There's no way I know of within the expression of the anonymous function to have it select which output to return from a function with multiple possible output arguments. However, you can return multiple outputs when you evaluate the anonymous function. Here's an example using the function MAX:
>> data = [1 3 2 5 4]; %# Sample data
>> fcn = #(x) max(x); %# An anonymous function with multiple possible outputs
>> [maxValue,maxIndex] = fcn(data) %# Get two outputs when evaluating fcn
maxValue =
5 %# The maximum value (output 1 from max)
maxIndex =
4 %# The index of the maximum value (output 2 from max)
Also, the best way to handle the specific example you give above is to actually just use the function handle #ttest2 as the input to CELLFUN, then get the multiple outputs from CELLFUN itself:
[junk,probabilities] = cellfun(#ttest2,cellArray1,cellArray2);
On newer versions of MATLAB, you can replace the variable junk with ~ to ignore the first output argument.

One way to do this is to define the function:
function varargout = getOutput(func,outputNo,varargin)
varargout = cell(max(outputNo),1);
[varargout{:}] = func(varargin{:});
varargout = varargout(outputNo);
end
and then getOutput(#ttest2,2,u,v) gives only the p-value.
To use it in a cellfun you would need to run:
probabilities = cellfun(#(u,v)getOutput(#ttest2,2,u,v)...
This eliminates the need to write a wrapper every time, but then you have to make sure this function is always in the path.

Related

How to assign each element/column of output to a different variable

In Matlab some functions adapt their output to the number of output variables in the call. For example I can do:
A=[[1 2 3];[4 5 6]];
s=size(A);
And I get
s=[2, 3];
But if I want to handle independently width and height I can do:
[h, w]=size(A);
And I get:
h=2;
w=3;
Now, if I have a function that always output a vector of let's say 3 elements. Is there a way to assign each element to a different variable?
I mean to avoid an scenery like this:
pos=getPosition();
X=pos(1);
Y=pos(2);
Z=pos(3);
I hope I have explained what I mean.
I've had the same problem. Mostly with functions handling coordinates as in your example. My solution was to create the following function:
function varargout = dealOneByOne(vector)
% Assign each column of vector to each variable on the output variables
%
for i=1:size(vector,2)
varargout{i}=vector(:,i);
end
end
Then you can just do
[X,Y,Z]=dealOneByOne(getPosition());
I'm not aware of a simpler way to do it.
Let's define a test function as follows:
function x = test()
x = [1 2 3];
end
Given the function above, this is what I would normally perform in order to split the output array into many distinct variables:
out = num2cell(test());
[a,b,c] = deal(out{:});
A wrapper function can be defined in order to avoid spreading the above assignment into multiple lines:
[a,b,c] = vout_num(test());
function varargout = vout_num(x)
C = num2cell(x);
varargout = C(:).';
end
In your example, the wrapper function would be used as follows:
[X,Y,Z] = vout_num(getPosition());

Defining a function with multiple outputs that can't be organised into a matrix

Is there any natural way to define a MATLAB function with multiple outputs that cannot or are inappropriate to "stack" into a matrix? For example, what if I want a function f that returns a 3x3 matrix A and a 4x4 matrix B?
I'm really surprised that this would even be an issue in MATLAB. Because in Python, all we need to do is return A, B which returns a tuple of the two. However it seems that MATLAB doesn't quite support the idea of containers. As a non-elegant workaround, I can use a struct to put the two pieces of data in, and the function goes something like:
function re = f(x)
%f: returns two dimensional-inconsistent matrices A and B
% function body as follows
....
A = ...;
B = ...;
% put data into the struct 're'
re.A = A;
re.B = B;
end
Apart from possible performance issues, this approach looks very unnatural and clumsy. Is there any better approach?
In MATLAB you can return any number of outputs with this syntax:
function [A,B] = f(x)
A = ...;
B = ...;
end
that is an even elegant solution than tuples used in python.
You can even control the behavior with the number of inputs and outputs (nargin and nargout) and discard outputs with a tilde. More information here.
I cannot think of a more elegant syntax.
Usually when having several outputs, one should declare the function as follows:
function [out1, out2, ... , outN] = funcName(in1,...,inM)
...
end
MATLAB also allows you to alter the behavior of your function based on the amount of requested inputs/outputs via the nargin/nargout functions, respectively (you can think of this as a form of overloading).
For example, you can specify as one of the inputs an array indicating which outputs you want the function to give, then populate the varargout cell array accordingly:
function varargout = funcName(in1,...,whichOut)
...
for indO = 1:numel(whichOut)
switch whichOut{indO}
case 'out1'
varargout{indO} = out1;
case 'out2'
... etc
case 'out6'
varargout{indO} = out6;
end
end
then call it using [out6, out1] = funcName(inp, {'out6','out1'});
See also varargin.

Keeping Some MATLAB Function Input Arguments Inactive

I have a function which takes 11 pairs of input arguments (each pair representing a type of process and an input commodity) and calculates a result based on all of those 22 values. However, I would like to make the function flexible such that if I wanted to use, for example, 3 pairs of input arguments rather than 11, it would still come up with a result and meanwhile ignore the other 8 pairs of unused arguments. Can you please tell me the simplest way to do that?
I've tried using varargin but when I pass fewer than 22 values as the input arguments, MATLAB tells me that the 'the (varargin) index (in the function file) exceeds the marix dimensions.'
Is there any way to pass 'inactive' input arguments so that MATLAB simply doesn't perform any operation on them?
Thanks.
Here's a sample of my code in the function file:
function [ Eprout,AnnEprout,Demand,AnnDemand,Status,AnnStatus ] = supdem(time, country, weights,supdataset,output, demdataset,... process1,process2,process3,process4,process5,process6,process7,process8,process9,process10,process11,... ipcom1,ipcom2,ipcom3,ipcom4,ipcom5,ipcom6,ipcom7,ipcom8,ipcom9,ipcom10,ipcom11)
Eprout = (sum(sum(supdataset(time,country,process1,ipcom1,output)))+sum(sum(supdataset(time,country, process2,ipcom2,output)))+ ... sum(sum(supdataset(time,country,process3,ipcom3,output)))+sum(sum(supdataset(time,country, process4,ipcom4,output)))+ ... sum(sum(supdataset(time,country,process5,ipcom5,output)))+sum(sum(supdataset(time,country, process6,ipcom6,output)))+... sum(sum(supdataset(time,country,process7,ipcom7,output)))+sum(sum(supdataset(time,country, process8,ipcom8,output)))+ ... sum(sum(supdataset(time,country,process9,ipcom9,output)))+sum(sum(supdataset(time,country, process10,ipcom10,output)))+... sum(sum(supdataset(time,country,process11,ipcom11,output))))/1000;
There are a number of ways of doing this. A simple alternative to varargin is to pass a logical vector with 0/1 values. In your case, the vector would contain 11 entries. The value of each entry would signal to the function whether to expect that variable pair in a separate array. Within the function you could have a series of if statements to check whether an entry in v is 1 or 0, for instance:
function [myoutputs] = myfunction(array_1,array_2,...., v);
default_1 = some_values1; % change some_values1 to whatever should be defaults for variable 2
default_2 = some_values2; % change some_values2 to whatever should be defaults for variable 2
% ... additional default initializations
if v(1)
pair_1 = array_1;
else
pair_1 = default_1;
end
% ... if statements for remaining pairs...
% ... use pair_1 pair_2 ...
For instance, passing the vector
v = [1 zeros(1,9) 1];
would indicate to the function that only the first and last parameter pairs are to be used.
You should still pass 11 pairs, but the content of the pairs you do not want to use can be empty or some other value.

define anonymous function as 2 of 4 outputs of m file function

I have an m-file function with 4 outputs. I would like to define an anonymous function that has the same inputs, but only produces 2 of the four outputs. Is this possible?
AFAIK, you can't do this with just an inline anonymous function, because that Matlab syntax doesn't provide a way of capturing and indexing in to multiple outputs of a function in a single expression. But you can write a couple reusable helper functions that do so, and then define anonymous functions using them.
Let's say your four argout function is named "f4".
function varargout = f4(x)
%F4 Dummy function that returns 4 argouts holding identifying indexes
varargout = num2cell(1:4);
Here's a reusable helper function that remaps outputs of a function call.
function varargout = callandmap(fcn, ix, varargin)
%CALLANDMAP Call a function and rearrange its output arguments
tmp = cell(1,max(ix)); % Capture up to the last argout used
[tmp{:}] = fcn(varargin{:}); % Call the original function
varargout = tmp(ix); % Remap the outputs
Now you can make anonymous, argout-remapping functions like this. Here, g holds an anonymous function that takes the same inputs as your original function, but just returns 2 of its original 4 outputs.
>> g = #(varargin) callandmap(#f4, [2 4], varargin{:})
g =
#(varargin)callandmap(#f4,[2,4],varargin{:})
>> [a,b] = g('dummy') % gets argouts 2 and 4 from original f4() function
a =
2
b =
4
>>
Using varargin allows you to omit trailing arguments when the resulting function handle is called. If you know all argins will always be provided, you can use named argins for readability if you want.
You can get even fancier and do this with a closure.
function fcn = mapargout(fcnIn, ixArgout)
%MAPARGOUT Create wrapper function that selects or reorders argouts
%
% fcn = argoutselector(fcnIn, ixArgout)
%
% Wraps a given function handle in a function that rearranges its argouts.
% This uses closures so it may have performance impacts.
%
% FcnIn is a function handle to wrap.
%
% IxArgout is a list of indexes in to the original functions argout list
% that should be used as the outputs of the new function.
%
% Returns a function handle to a new function.
fcn = #extractor;
function varargout = extractor(varargin)
n = max(ixArgout);
tmp = cell(1,n);
% Call the wrapped function, capturing all the original argouts
[tmp{:}] = fcnIn(varargin{:});
% And then select the ones you want
varargout = tmp(ixArgout);
end
end
This results in simpler code for creating the anonymous function. And you could compose it with other function wrapper calls.
>> g = mapargout(#f4, [2 4])
g =
#mapargout/extractor
>> [a,b] = g('dummy')
a =
2
b =
4
>>
But closures can be tricky to work with in Matlab and may have performance implications. The callandmap approach is probably preferable unless you need the extra power.
If the two outputs are #1 and #2, everything is fine, and you don't have to worry about the other two outputs.
If the two outputs are any two others, you have two options
(1) Create a wrapper function with two outputs (note that in newer versions of Matlab you can replace the unused outputs dummy by ~.
function [out1,out2] = wrapperFunction(in1,in2,in3)
[dummy,out1,dummy,out2] = mainFunction(in1,in2,in3);
(2) Add another input variable that allows you to switch your function's behavior
function varargout = mainFunction(in1,in2,in3,outputSwitch)
%# make output switch optional
if nargin < 4 || isempty(outputSwitch)
outputSwitch = 0;
end
%# calculation here that creates out1-4
if outputSwitch
%# the special case where we only want outputs 2 and 4
varargout = {out2,out4};
else
%# return all four outputs
varargout = {out1,out2,out3,out4}
end
Then you can create the anonymous function as usual.

Skipping outputs with anonymous function in MATLAB

Say I want to create an anonymous function from a m-file-function that returns two outputs. Is it possible to set up the anonymous function such that it only returns the second output from the m-file-function?
Example: ttest2 returns two outputs, t/f and a probability. If I want to use the t-test with cellfun, I might only be interested in collecting the probabilities, i.e. I'd like to write something like this
probabilities = cellfun(#(u,v)ttest2(u,v)%take only second output%,cellArray1,cellArray2)
There's no way I know of within the expression of the anonymous function to have it select which output to return from a function with multiple possible output arguments. However, you can return multiple outputs when you evaluate the anonymous function. Here's an example using the function MAX:
>> data = [1 3 2 5 4]; %# Sample data
>> fcn = #(x) max(x); %# An anonymous function with multiple possible outputs
>> [maxValue,maxIndex] = fcn(data) %# Get two outputs when evaluating fcn
maxValue =
5 %# The maximum value (output 1 from max)
maxIndex =
4 %# The index of the maximum value (output 2 from max)
Also, the best way to handle the specific example you give above is to actually just use the function handle #ttest2 as the input to CELLFUN, then get the multiple outputs from CELLFUN itself:
[junk,probabilities] = cellfun(#ttest2,cellArray1,cellArray2);
On newer versions of MATLAB, you can replace the variable junk with ~ to ignore the first output argument.
One way to do this is to define the function:
function varargout = getOutput(func,outputNo,varargin)
varargout = cell(max(outputNo),1);
[varargout{:}] = func(varargin{:});
varargout = varargout(outputNo);
end
and then getOutput(#ttest2,2,u,v) gives only the p-value.
To use it in a cellfun you would need to run:
probabilities = cellfun(#(u,v)getOutput(#ttest2,2,u,v)...
This eliminates the need to write a wrapper every time, but then you have to make sure this function is always in the path.