Well, simply define a new anonymous function as @(x) myFunc(x,4) and use it this way:
F = cellfun(@(x) myFunc(x,4), C)
Answer from knedlsepp on Stack Overflowmatlab - Application of cellfun with multiple arguments - Stack Overflow
is it possible to use multiple functions in cellfun
Using Cellfun for multiple inputs
can i used cellfun with a function which has more than one input?
Hiya,
I'm trying to specifically use cellfun to use the function extractFeatures on multiple detected points from a SURF detection in the computer vision toolbox. The problem I'm having is that the inputs are both cell arrays which doesn't allow me to put one of them as the cell array. Should add I'm trying to extract features for 118 images.
Here is what I've tried:
g = cellfun(@rgb2gray,images,'UniformOutput',false); points = cellfun(@detectSURFFeatures,g,'UniformOutput',false); [features, valid_points] = cellfun(@(x) extractFeatures(G, points), g);
Where g & points are cell arrays with size 1x118.
Any help is much appreciated.
You can do this using an anonymous function that calls myfun with the two additional arguments:
cellfun(@(x) myfun(x,const1,const2), cellarray)
Another trick is to use ARRAYFUN on the indices:
arrayfun(@(k) myfun(cellarray{k},const1,const2), 1:numel(cellarray))
if the return values of myfun are not scalars, you might want to set the 'UniformOutput',false option.
To do this very fast, do not use either cellfun or str2double. Some possibilities:
strjoin with sscanf
Use strjoin to combine the strings in cell array x into a single long space-delimited string, which can then be parsed very quickly with sscanf:
sscanf(strjoin(reshape(x,1,[])),'%f')
Note the reshape is included to guarantee the cell array is a row, as required by strjoin. A simple permute (.') could be used if you know x is a column, or nothing if x is already a row.
vertcat (or str2mat) with sscanf
Instead of strjoin, form a virtual comma-separated list of strings with x{:} and vertically concatenate them with vertcat (if each string has the same number of characters). Transpose this 2D character array and sscanf can again parse it quickly in a single shot:
sscanf(vertcat(x{:})','%f');
Or if the number of characters varies from string to string, you can use str2mat, which creates a space-padded 2D character array that sscanf also happily reads:
sscanf(str2mat(x)','%f');
test
Create a cell array of string representations of 10,000 random numbers:
>> x = sprintfc('%f',rand(1e4,1));
Note the use of the undocumented sprintfc to print to cells.
Reference methods:
>> tic; d0 = str2double(x); toc
Elapsed time is 0.302148 seconds.
>> tic; d1 = cellfun(@(x) sscanf(x,'%f'),x); toc
Elapsed time is 0.277386 seconds.
>> isequal(d0,d1)
ans =
1
strjoin and vertcat:
>> tic; d2 = sscanf(strjoin(reshape(x,1,[])),'%f'); toc
Elapsed time is 0.068129 seconds.
>> isequal(d0,d2)
ans =
1
>> tic; d3 = sscanf(vertcat(x{:}).','%f'); toc
Elapsed time is 0.024312 seconds.
>> isequal(d0,d3)
ans =
1
>> tic; d4 = sscanf(str2mat(x).','%f'); toc
Elapsed time is 0.011917 seconds.
>> isequal(d0,d4)
ans =
1
Note: these numbers are ballpark as then should be run over multiple iterations inside of a script or function, but all code is warmed. Try them out.
How about a wrapper for the sscanf?
myWrapper = @(x) sscanf(x, '%f')
x={'0.17106'; '2.11462'; '4.13938'; '6.24203'}
cellfun(myWrapper,x)
str2double(x)
As constructed, the *fun family of functions exists for this purpose (e.g., cellfun is the pertinent one here). They are other questions on the use and performance of these functions.
However, if you construct f as a function that constructs a cell array as
f = @(x) {sin(x), cos(x), x+4};
then you can call the function more naturally: f([1,2,3]) for example.
This method also avoids the need for the ('UniformOutput',false) option pair needed by cellfun for non-scalar argument.
You can also use regular double arrays, but then you need to be wary of input shape for concatenation purposes: @(x) [sin(x), cos(x), x+4] vs. @(x) [sin(x); cos(x); x+4].
I'm just posting these benchmarking results here, just to illustrate that loops not necessarily are slower than other approaches:
f = {@sin, @cos, @(x)x+4};
x = 1:100;
tic
for ii = 1:1000
for jj = 1:numel(f)
res{jj} = f{jj}(x);
end
end
toc
tic
for ii = 1:1000
res = cellfun(@(arg) arg(x),functions,'uni',0);
end
toc
Elapsed time is 0.042201 seconds.
Elapsed time is 0.179229 seconds.
Troy's answer is almost twice as fast as the loop approach:
tic
for ii = 1:1000
res = f((1:100).');
end
toc
Elapsed time is 0.025378 seconds.