Error with arrayfun - matlab

I have the following function:
function x = dataParser(y)
%// Importing list of places
places = textread('UKPlaceNames.txt' ,'%s');
%// Picking two places
place = char(places(y)); %// Converting them to an array of chars
placeInt = place - 'A' + 1;
x = placeInt;
end
In a separate function, I create:
myVector = 1:6
and then call
myVectorB = arrayfun(dataParser, myVector)
However, MATLAB throws an error on:
place = char(places(y));
stating that there are not enough parameters, where
places = textread('test.txt' ,'%s');
I am a bit confused as to where the error is, since the function takes one paramater and I am providing it...
Thanks!

You should do the following in your main script/function:
myVectorB = arrayfun(#dataParser, myVector)
Note the # in front of dataParser: this passes a function handle of dataParser to arrayfun, instead of evaluating the function dataParser() and passing the result to arrayfun.

Related

function handles in Octave

I have a question regarding function(handles) in Octave.
So, I want to call a function, which accepts two variables and returns two(the implementation is faulty; but not relevant in this case).
According to the documentation this should be quite straightforward:
function [ret-list] = name (arg-list)
body
endfunction
I'm trying the following:
function two_d_comp = twodcomp
twodcomp.twoDperp=#perp;
^
end
function twoDperp[vmag, vangle]=perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end;
I saved the function in a file called twodcomp.m.
When I call the function as follows:
[X, Y] = twodcomp.twoDperp(1,2)
Octave spits out the following:
error: #perp: no function and no method found
error: called from
twodcomp at line 2 column 20
I managed to remove the error by removing the output arguments vmag and vangle, as follows:
function twoDperp=perp(x,y)
But this is obviously not really what I want.
Do you guys happen to have some pointers as to what I'm doing wrong?
Cheers
Your initial function twodcomp: you cannot have the output variable (before the =) be named the same as your function name (after the =).
Then if you want to assign an anonymous function (MATLAB docs, Octave docs) using the # notation, you can still pass the desired inputs.
So rewrite it like:
% Include empty parentheses after a function name to make it clear which is the output
function output = twodcomp()
% Not sure why you're assigning this function to a struct, but
% still give yourself the ability to pass arguments.
% I'm assuming you want to use the output variable,
% and not reuse the main function name (again)
output.twoDperp = #(x,y) perp(x,y);
end
With your second function, you just need to remove the twoDperp before your output arguments. In your question you state the expected syntax from the docs, but then didn't follow it...
function [vmag, vangle] = perp(x,y)
W = hypot(y,x);
vmag = y/W;
vangle = x/y;
end
Now these can be used like so:
% Deliberately using different variable names to make it clear where things
% overlap from the function output. twodcomp output is some struct.
myStruct = twodcomp();
% The output struct has the field "twoDperp" which is a function with 2 outputs
[m, a] = myStruct.twoDperp(1,2);

MATLAB - the function returns unwanted output

and I am pretty new at it. I wrote the simple function below, which gets a pair and returns the polar form
function [r,a] = rect2polar(x,y)
r = sqrt(x^2 + y^2);
a = atan(y/x);
[r,a]
end
and when I try for example rect2polar(3,5) it gives me the next output:
ans =
5.8310 1.0304
ans =
5.8310
It returns the desired output, plus the output 5.8310, in other words it returns the variable r in the function for the second time. How can I fix this? Writing
rect2polar(3,5);
helped (the difference is that I wrote ; at the end), but it doesn't feel right. Any help is appreciated, thanks!
The first displayed part,
ans =
5.8310 1.0304
is produced by this line in your function
[r,a]
Since it is missing a ;, Matlab displays the result.
The second part,
ans =
5.8310
is produced because when you call the function as rect2polar(3,5) you are indicating that you want only one output, namely the first, which is displayed after the function returns.
So, the solution would be:
Remove the line [r, a] in your function, which is doing nothing but display what the function will output;
Call your function as [out1, out2] = rect2polar(3,5).
Or, if you want the function to return a vector:
function out = rect2polar(x,y)
r = sqrt(x^2 + y^2);
a = atan(y/x);
out = [r,a];
end

Conversion function for 3D value into 2D in MATLAB

I have written a function for converting 3D values into 2D, but not able to get it working may be I am parsing the wrong values.
I am passing the value in the valuse as 2 coordinates and trying to get into Output in 2D. Can anyone please do the correction in the function below and help me in running the function?
% Perspective Projection
function Output = perspective_projection(Input)
Output = zeros(size(Input));
for ii = 1: length(Input)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2)=Input(ii,2)/Input(ii,3);
end
value = [6,4,2];
[a1,b1] = perspective_projection(a1)
BSXFUN method as suggested by Rody is an elegant way, but if you would like to keep your loop, try this -
% Perspective Projection
function Output = perspective_projection(Input)
Output = zeros(size(Input,1),2);
for ii = 1: size(Input,1)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2) = Input(ii,2)/Input(ii,3);
end
If I understand you correctly, you should rewrite your function as:
function Output = perspective_projection(Input)
Output = bsxfun(#rdivide, Input(:,1:2), Input(:,3));
end
or, judging from the way you seem to be calling it:
function [OutputX,OutputY] = perspective_projection(Input)
OutputX = Input(:,1)./Input(:,3);
OutputY = Input(:,2)./Input(:,3);
end
Note that your function is quite simple (I wouldn't even use a function):
[X,Y] = deal(Input(:,1)./Input(:,3), Input(:,2)./Input(:,3));
As for your original function: the error is in the initialization:
function Output = perspective_projection(Input)
%// WRONG: this initializes a 3D array!
Output = zeros(size(Input));
%// ...but you want a 2D array
for ii = 1: length(Input)
Output(ii,1) = Input(ii,1)/Input(ii,3);
Output(ii,2) = Input(ii,2)/Input(ii,3);
end
end
and of course, the multiple outputs (but it's not quite clear to me whether you want that or not...)

First input must be function handle error using arrayfun()

I'm trying to use arrayfun() to map a function over a cell array. The following is happening:
>> arrayfun(solveFunc, equArray)
Error using arrayfun
First input must be a function handle.
Error in solve>genGuess (line 33)
funcVals = abs(arrayfun(inFunc, xValues));
Error in solve (line 8)
x = genGuess(inFunc, varargin{1}, varargin{2});
Error in makeSolveFunc>#(func)solve(func,start,stop) (line 3)
sFunc = #(func) solve(func, start, stop);
But, the first input IS a function handle. Also... if I manually apply the function to each element of the provided cell array, everything works fine:
>> solveFunc(equArray{1})
ans =
4.7335
>> solveFunc(equArray{2})
ans =
4.7356
Does anyone know why this would be happening? I assumed that if I could manually apply the function to each element of my array, and the return type of the function was consistent and one of the allowed types (you can't for example have arrayfun return an array of function handles... I already tried doing that), it should work. Perhaps that is not the only requirement.
Here is some code that generates this error:
solve.m
function solution = solve(inFunc, start, stop)
%SOLVE solve an equation using Newton's Method
x = genGuess(inFunc, start, stop);
for i = 1:100
m = getSlope(inFunc, x);
x = (m*x - inFunc(x))/m;
end
solution = x;
end
function slope = getSlope(inFunc, x)
%SLOPE calculate the slope at a given point
inc = 1e-5;
if x ~= 0
inc = inc * x;
end
slope = (inFunc(x + inc) - inFunc(x - inc))/(2*inc);
end
function guess = genGuess(inFunc, start, stop)
%GENGUESS get an initial guess to the solution
xValues = linspace(start, stop, 101);
funcVals = abs(arrayfun(inFunc, xValues));
[~, minIndex] = min(funcVals);
guess = xValues(minIndex);
end
charEqu.m
function equ = charEqu(a)
%CHAREQU create a KP model characteristic equation with provided p
equ = #(x) x + a;
end
makeSolveFunc.m
function sFunc = makeSolveFunc(start, stop)
%MAKESOLVEFUNC return a function that solves an equation
sFunc = #(func) solve(func, start, stop);
end
test.m
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = arrayfun(solveFunc, equArray);
I have narrowed down the error to something in genGuess(). For some reason, in the line funcVals = abs(arrayfun(inFunc, xValues)); the variable inFunc is a 1x1 cell array containing a function handle. I have no idea why that would be the case. I traced this back to the anonymous function call #(func) solve(func, start, stop); in the makeSolveFunc() function. There it is still a 1x1 cell array containing a function handle. I'm not really sure where that cell array is coming from as that function is getting called from arrayfun().
Background information on what I'm trying to do in case someone wants to suggest a better way:
I'm trying to solve equations using Newton's method. I have written a function that can solve an equation given an initial guess range. This function is the solve() function you can see in the first error message. It takes a function, and the guess range and returns a function that I'm calling solveFunc(). solveFunc() takes a function and solves it using the initial guess range previously provided.
Maybe I'm just too used to functional programming and should just use a loop.
If the arguments passed to the function handle are contents of elements of a cell array, you need to use cellfun instead of arrayfun:
cellfun(solveFunc, equArray)
This is equivalent to
for i=1:length(equArray)
out(i) = solveFunc(equArray{i});
end
since solveFunc is already a function handle.
Check where the error comes from. This line causes the error:
funcVals = abs(arrayfun(inFunc, xValues));
The first input argument is a 1x1 cell containing one function handle. This is caused because equArray is a cell, thus use cellfun as Jonas already mentioned:
pArray = 1:5;
equArray = cell(1,arrayLen);
for i = 1:5
equArray{i} = charEqu(pArray(i));
end
solveFunc = makeSolveFunc(1.1*pi, 2*pi);
alphaAArray = cellfun(solveFunc, equArray);

Storing function handles in array and then adding them in MATLAB

I am trying to store function handles in array by running a loop and then adding them.
for i = 1:n^2
x1 = x_coord(elements(i,1));
x2 = x_coord(elements(i,2));
x3 = x_coord(elements(i,3));
x4 = x_coord(elements(i,4));
y1 = y_coord(elements(i,1));
y2 = y_coord(elements(i,2));
y3 = y_coord(elements(i,3));
y4 = y_coord(elements(i,4));
SF(elements(i,1)) = #(x,y)((x-x3)*(y-y3)/((x1-x3)*(y1-y3)) + SF(elements(i,1)(x,y))
end
Here I am saving function handles in array SF and then adding them inside the loop.
But I am getting this error:
Error: ()-indexing must appear last in an index expression.
PLEASE HELP.
When trying something this complicated, break it down and try smaller pieces. For example, when I run this at the command line:
F(1) = #(x,y)(x+y);
F(2) = #(x,y)(x+y+2);
I get the following error message: Nonscalar arrays of function handles are not allowed; use cell arrays instead.
Oops. I guess you need this instead:
F{1} = #(x,y)(x+y);
F{2} = #(x,y)(x+y+2);
And now, sure enough, F{1}(1,2) works as expected.
What's not going to work is the overall logic of the program, as you're trying to recursively define SF(elements(i,1)) in terms of itself, which doesn't make any sense. Try some more smaller pieces, like I show above, to experiment with function handles defined in terms of other function handles. You're likely to find some surprises.