7

My situation is that I would like to map a scalar array A by a function with handle fun sending a row vector to a row vector, to acquire B, such that B(i,:) = fun(A(i,:)).

The most reasonable solution I could think of looks like:

temp = mat2cell(A,ones(1,size(A,1)),size(A,2));
B = cell2mat(cellfun(fun,temp,'UniformOutput',0));

However, the conversion to cells and back seems like overkill (and is assumably computationally expensive). It is also not clear to me why cellfun complains about non-uniform output. Does a more efficient way jump to mind?

1

4 Answers 4

4

There's another solution that employs accumarray. Although not as fancy as bsxfun, it doesn't require declaring a helper function:

subs = ndgrid(1:size(A, 1));
B = accumarray(subs(:), A(:), [], @fun); %// @fun is the function handle
Sign up to request clarification or add additional context in comments.

Comments

4

You can do this without using cell arrays at all with bsxfun.

Using Marcin's example data and function:

A =[ 0.5669    0.4315    0.4515    0.7664    0.5923; ...
     0.8337    0.7317    0.4898    0.2535    0.7506; ...
     0.3321    0.5424    0.4585    0.8004    0.9564];

fun = @(x,y) x*2;
B= bsxfun(fun,A,1);

B =

    1.1338    0.8630    0.9030    1.5328    1.1846
    1.6674    1.4634    0.9796    0.5070    1.5012
    0.6642    1.0848    0.9170    1.6008    1.9128

Edit:

As Eitan noted, fun above may need to be a wrapper on your 'real' anonymous function so it would be more complete to show my solution as:

fun = @(x) x *2;        % Replace with actual anonymous function
fun2 = @(x,y) fun(x);   % Wrapper on fun to discard unused 2nd parameter
B= bsxfun(fun2,A,1);

5 Comments

Nice use of bsxfun, but this applys function to one value in a at the time, or to one row at the time?
@Marcin Should a scalar be passed to bsxfun as one of the arrays, bsxfun would perform scalar expansion and apply applies it to every element of the other array (a recent question deals with this issue).
@grantnz +1, but the fun in the question is unary. You should note that your fun is a wrapper function defined for being used in bsxfun...
@EitanT. Yes, this solution does require a simple wrapper to discard the unused 2nd argument although if the primary function is an anonymous function it could easily discard a dummy 2nd parameter.
@grantnz Easily, yes. But this should be noted, as it seems at first glance that you're feeding bsxfun with the original function.
4

I know this is an old post, but in case someone else sees this, Matlab added rowfun to the 2013b release which can evaluate rows of tables and returns a column vector. Here is an example:

f = @(c) sum(c.^2);

x=[1 2;
   3 4;
   5 6];

z=table2array(rowfun(f,table(x)))

z=
   5
  25
  61

Comments

2

I think you could do as follows, if I understand what u want to do:

A = rand(3, 5);
fun = @(x) x*2;
B = cell2mat(arrayfun(@(i) fun(A(i, :)), 1:size(A, 1), 'UniformOutput', false)');

% example results:
A =

    0.5669    0.4315    0.4515    0.7664    0.5923
    0.8337    0.7317    0.4898    0.2535    0.7506
    0.3321    0.5424    0.4585    0.8004    0.9564


B =

    1.1338    0.8630    0.9030    1.5328    1.1845
    1.6675    1.4635    0.9795    0.5071    1.5013
    0.6642    1.0848    0.9169    1.6008    1.9128

This will apply fun to each element of row in A. This is based on the post here. Also there u find more info and explanation what is happening or alternative ways of applying function to rows in an array.

2 Comments

Your implementation looks identical to mine. I'll check the other thread for more info -- still curious principally in whether transforming to cells is the most sane way to proceed.
Thanks, ran into the same problem, this seems to be the most simple way to achieve the right result.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.