6

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?

Eugene Shvarts
  • 205
  • 2
  • 8
  • related question: [how to apply a function to every row in matlab?](http://stackoverflow.com/q/2307249/1336150) – Eitan T Aug 13 '13 at 07:39

4 Answers4

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
Eitan T
  • 32,660
  • 14
  • 72
  • 109
3

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);
grantnz
  • 7,322
  • 1
  • 31
  • 38
  • Nice use of bsxfun, but this applys function to one value in a at the time, or to one row at the time? – Marcin Aug 13 '13 at 03:57
  • @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](http://stackoverflow.com/q/18079629/1336150) deals with this issue). – Eitan T Aug 13 '13 at 06:31
  • @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`... – Eitan T Aug 13 '13 at 06:35
  • @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 Aug 13 '13 at 07:20
  • 1
    @grantnz Easily, yes. But this should be noted, as it seems at first glance that you're feeding `bsxfun` with the original function. – Eitan T Aug 13 '13 at 07:35
3

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
rickcjmac
  • 31
  • 1
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.

Community
  • 1
  • 1
Marcin
  • 215,873
  • 14
  • 235
  • 294
  • 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. – Eugene Shvarts Aug 13 '13 at 03:15
  • Thanks, ran into the same problem, this seems to be the most simple way to achieve the right result. – Realhermit Mar 31 '17 at 00:09