4

How can I access both arguments of ismember when it is used inside splitapply?

slitapply only returns scalar values for each group, so in order to compute nonscalar values for each group (as returned by the first argument of ismemebr), one has to enclose the anonymous function (in this case ismember) inside curly brackets {} to return a cell array.

But now, when I provide two output arguments to splitapply, I get an error:

Output argument "varargout{2}" (and maybe others) not assigned during call to "@(x,y) {ismember(x,y)}"

ADD 1

I can create another function, say, ismember2cell which would apply ismember and turn outputs into cell arrays:

function [a, b] = ismember2cell(x,y)
  [a,b] = ismember(x,y);
  a = {a};
  b = {b};
end

but maybe there is a solution which doesn't require this workaround.

Confounded
  • 446
  • 6
  • 19

2 Answers2

3

One potentially faster option is to just do what splitapply is already doing under the hood by splitting your data into cell arrays (using functions like mat2cell or accumarray) and then using cellfun to apply your function across them. Using cellfun will allow you to easily capture multiple outputs (such as from ismember). For example:

% Sample data:
A = [1 2 3 4 5];
B = [1 2 1 5 5];
G = [1 1 1 2 2];  % Group index

% Group data into cell arrays:
cellA = accumarray(G(:), A(:), [], @(x) {x(:).'});  % See note below about (:).' syntax
cellB = accumarray(G(:), B(:), [], @(x) {x(:).'});

% Apply function:
[Lia, Locb] = cellfun(@ismember, cellA, cellB, 'UniformOutput', false);

NOTE: My sample data are row vectors, but I had to use the colon operator to reshape them into column vectors when passing them to accumarray (it wants columns). Once distributed into a cell array, each piece of the vector would still be a column vector, and I simply wanted to keep them as row vectors to match the original sample data. The syntax (:).' is a colon reshaping followed by a nonconjugate transpose, ensuring a row vector as a result no matter the shape of x. In this case I probably could have just used .', but I've gotten into the habit of never assuming what the shape of a variable is.

gnovice
  • 125,304
  • 15
  • 256
  • 359
  • Thank you. This looks interesting. Will investigate and come back. – Confounded Nov 06 '17 at 17:24
  • Could you please explain / point to an explanation of the syntax used in the creation of cell arrays `x(:).'`? In particular, what does the dot `.` do? Thanks – Confounded Nov 06 '17 at 17:54
  • @Confounded: I added an extra note to the answer. Hope that clears up what I was doing. – gnovice Nov 06 '17 at 18:09
0

I cannot find a global solution, but the accepted answer of this post helps me to define a helper function for your problem:

function varargout = out2cell(varargin)
[x{1:nargout}]=feval(varargin{:});
varargout = num2cell(x);

I think that you may succeed in calling

splitapply(@(x,y) out2cell(@ismember, x, y), A, B);
Bentoy13
  • 4,886
  • 1
  • 20
  • 33