Errors for groupsummary() using function handles

25 次查看(过去 30 天)
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.

采纳的回答

Cris LaPierre
Cris LaPierre 2021-8-20
编辑:Cris LaPierre 2021-8-20
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 个评论
xitram
xitram 2021-8-20
编辑:xitram 2021-8-20
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 2021-8-20
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.

请先登录,再进行评论。

更多回答(1 个)

Dave B
Dave B 2021-8-20
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 个评论
xitram
xitram 2021-8-20
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 2021-8-20
@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!

请先登录,再进行评论。

类别

Help CenterFile Exchange 中查找有关 Resizing and Reshaping Matrices 的更多信息

产品


版本

R2018b

Community Treasure Hunt

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

Start Hunting!

Translated by