Errors for groupsummary() using function handles

23 visualizzazioni (ultimi 30 giorni)
I am struggling to do a groupwise integration with groupsummary(...) using a handle to the trapz() function as the method.
Please note:
  • This is about correct syntax/logic, not the numerical result.
  • I am still on R2018b.
The doc.s for the current R2021a have more info for this case (which is not in R2018b), pointing out that "When the input data is a table T and you specify a function handle for method that takes more than one input argument, you must specify datavars."
R2021a also has an example but this uses the function xcov() which seems to be available only in the Signal Processing toolkit (or perhaps now in Matlab, but only after R2018b).
See the code below for (some of) the various attempts I have made, and the various resulting errors.
Using trapz() with only one argument does in fact work, but of course that way the intended array (tbA.a) is not used for the "integration steps".
It also seems that there is (or was) some ?bug with groupsummary(), but it's not clear to me if/how this has any relevance to the problem.
What am I missing?
Thanks for any pointers.
Full (non- :-)working demo example:
% set up x and y variables, column vectors for easier checking
a = [0.0:.01:0.99]' ;
b = sin(a) ;
%generate group IDs 1 ... 5, group size varies
grpID = [repmat(1,22,1);repmat(2,18,1);repmat(3,24,1);repmat(4,16,1); ...
repmat(5,20,1) ...
] ;
% create table
tbA = table(grpID,a,b,'VariableNames',{'grpID','a','b'}) ;
fh = @trapz ; %function handle for trapz(...)
%testing the handle
res1 = fh(b); % does work: res1 = 45.1306
res2 = fh(a,b); % also works: res2 = 0.4513
% integr = groupsummary(tbA,'grpID',fh(b)) ;
%ERR: Second argument, number of bins, must be a positive integer.
% [mis-parsed, see R2021a doc.s: datavars needed, and apparently even
% when function has only *one* argument]
% integr = groupsummary(tbA,'grpID',fh(b),'b') ;
%ERR: Method must be a valid name, a function handle, or a cell array
% containing valid methods.
% What's wrong with the handle here?
% integr = groupsummary(tbA,'grpID',fh(a,b),'b') ;
%ERR: Method must be a valid name, a function handle, or a cell array
% containing valid methods.
% Ditto
% integr = groupsummary(tbA,'grpID',@(x,y) trapz(x,y),{"a","b"}) ;
%ERR: Invalid data variables.
% This is the same syntax as in R2021a doc.s (see link above):
% "For example:
% groupsummary(T,groupvars,@(x,y) myFun(x,y),{"x1","y1"})
% calculates myFun(T.x1,T.y1) for each group."
integr = groupsummary(tbA,'grpID',@(x) trapz(x),'b') ;
% result: 5x3 table, integration results in integr.fun1_b
% This DOES work, but it uses trapz(...) with only *one* argument
% so is not using tbA.a for the integration steps.

Risposta accettata

Cris LaPierre
Cris LaPierre il 20 Ago 2021
Modificato: Cris LaPierre il 20 Ago 2021
If you try to run the function handle with multiple inputs example from the R2021a doc in R2018b, you will get an error. That suggests to me the functionality needed to use groupsummary with a function handle that accepts multiple inputs did not exist in 2018b.
You could try using findgroups and splitapply
% set up x and y variables, column vectors for easier checking
a = [0.0:.01:0.99]' ;
b = sin(a) ;
%generate group IDs 1 ... 5, group size varies
grpID = [repmat(1,22,1);repmat(2,18,1);repmat(3,24,1);repmat(4,16,1); ...
repmat(5,20,1) ...
] ;
% create table
tbA = table(grpID,a,b) ;
G = findgroups(tbA.grpID);
C = splitapply(@trapz,tbA.a,tbA.b,G)
C = 5×1
0.0220 0.0510 0.1130 0.0982 0.1480
  3 Commenti
xitram
xitram il 20 Ago 2021
Modificato: xitram il 20 Ago 2021
Thanks for the prompt reply! G seems somewhat redundant as it happens to replicate tbA.grpID, but only in this case -- using findgroups() is much more useful as it is more general, of course. As to the doc.s, I had also looked at the latest Release Notes but had naturally (Murphy's Law) missed this one somehow; thanks for the link. The old R2018b doc.s are a bit misleading as they only state "You can also specify a function handle that returns one element per group." without mentioning the limitation that the function must have only one input argument.
Cris LaPierre
Cris LaPierre il 20 Ago 2021
If you already have a grouping variable, you do not need to use findgroups.
% set up x and y variables, column vectors for easier checking
a = [0.0:.01:0.99]' ;
b = sin(a) ;
%generate group IDs 1 ... 5, group size varies
grpID = [repmat(1,22,1);repmat(2,18,1);repmat(3,24,1);repmat(4,16,1); ...
repmat(5,20,1) ...
] ;
% create table
tbA = table(grpID,a,b) ;
C = splitapply(@trapz,tbA.a,tbA.b,tbA.grpID)
C = 5×1
0.0220 0.0510 0.1130 0.0982 0.1480
I agree that it was unclear to me whether it was possible to use a function handle with multiple inputs in R2018b or not.

Accedi per commentare.

Più risposte (1)

Dave B
Dave B il 20 Ago 2021
I think the feature of accepting multiple arguments is trying to solve this exact problem, to work around this in 18b you can pack a and b into a cell:
a = [0.0:.01:0.99]' ;
b = sin(a) ;
grpID = [repmat(1,22,1);repmat(2,18,1);repmat(3,24,1);repmat(4,16,1); ...
repmat(5,20,1) ...
] ;
tbA = table(grpID,a,b)
tbA.c = mat2cell([tbA.a tbA.b],ones(height(tbA),1),2);
integr = groupsummary(tbA,'grpID', @foo, {'c'} )
And then define foo as:
function a=foo(x)
try
xx=cell2mat(x);
a=trapz(xx(:,1),xx(:,2));
catch
a=nan;
end
end
It's a little awkward. foo might be called a couple of times outside of for your groups (set a break point to see that). I used try catch with the reasoning that - if I can't get the result it should return a NaN.
  2 Commenti
xitram
xitram il 20 Ago 2021
Thanks for the fast response! The work-around may be a little awkward, but I find it very instructive: In Matlab I can't practice enough with regard to juggling matrices vs. tables vs. cells, or all of the above, at the same time... :-)
Dave B
Dave B il 20 Ago 2021
@Cris LaPierre's answer was better, I had forgotten that splitapply didn't have the one-arg limitation in the early releases but groupsummary did.
Hopefully features like the one that was added to groupsummary in R2020b mean that you don't have to juggle as often!

Accedi per commentare.

Categorie

Scopri di più su Resizing and Reshaping Matrices in Help Center e File Exchange

Prodotti


Release

R2018b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by