Split a table into groups and call a method with multiple parameters

I'm quite new to Matlab so this should be a fairly simple question.
I have the following table:
label team id
lab1 team1 403
lab2 team1 932
lab3 team1 264
lab4 team1 552
lab5 team2 374
lab6 team2 765
lab7 team2 639
lab8 team2 707
lab9 team3 1295
lab10 team3 274
lab11 team3 270
lab12 team3 349
lab13 team3 1280
lab14 team4 481
lab15 team4 1191
lab16 team4 236
lab17 team4 742
lab18 team4 1340
Also, I have a method like this:
CalculateGroupCentrality(A, L)
Where A is an adjacency matrix and L a line vector. What I would like to do is to split this table into line vectors - e.g., team1 - 403, 932, 264, 552 - and call the method CalculateGroupCentrality for each of the teams. Also, A (the adjacency matrix) should be the same for each call.
I tried something like this:
graph = read_gml('mygraph.gml');
callCalculateGroupCentrality = @(L)CalculateGroupCentrality(get_adjacency_matrix(graph),L);
G = findgroups(teamnetworkid.team);
centralities = splitapply(callCalculateGroupCentrality, teamnetworkid.id, G)
But that returns the following error:
Error using splitapply (line 132)
Applying the function '@(L)CalculateGroupCentrality(get_adjacency_matrix(graph), L)' to the 1st group of data generated the following error:
Subscripted assignment dimension mismatch.
I understand this might be simple, but not sure what I'm missing here.

 采纳的回答

Are you asking for something like this?(First and second column are char column arrays stored in cell arrays, that is what I did while constructing table and the following code works for that)
table2array(Tab(ismember(table2cell(Tab(:,2)),{'team1'}),3))
which results in
ans =
403
932
264
552

9 个评论

Something like that. It's just that I need to iterate over all groups/teams. Does that make sense? So, pull members for each team, and every time call that method for calculating group centrality. The method accepts the list of members.
The following might work(It groups according to team):
for i=1:18
label{i,1}=sprintf('label%i',i);
end
team={'team1','team1','team1','team1','team2','team2','team2','team2','team3','team3','team3','team3','team3','team4','team4','team4','team4','team4'};
team=team.';
id=[403 932 264 552 374 765 639 707 1295 274 270 349 1280 481 1191 236 742 1340];
id=id.';
Tab=table(label,team,id);
TeamUn=unique(table2cell(Tab(:,2)));
for i=1:numel(unique(Tab(:,2)))
Group{i}=table2array(Tab(ismember(table2cell(Tab(:,2)),TeamUn{i}),3));
end
The ID's are grouped within Group cell array.
In general there is absolutely no need to convert a table to a cell array (or anything else). You lose functionality rather than gain it by doing so.
Yes, but the user originally gathered those variables in table, therefore I did not change it for the sake of user.
My point was that once you've got a table there is no reason to convert back to matrix or cell using table2cell or table2array. It's completely unnecessary.
For example, your code can be replaced by:
Group = splitapply(@(v){v}, Tab.id, findgroups(Tab.team))
But even if you ignore that,
table2cell(Tab(:,2))
is
Tab{:, 2}
%or simply
Tab.team
and
table2array(Tab(ismember(table2cell(Tab(:,2)),TeamUn{i}),3))
is
Tab{ismember(Tab.team, TeamUn{i}, 3})
%or simply
Tab.id(ismember(Tab.team, TeamUn{i}))
Seems like I'm almost there... combining what @Guillaume suggested and what you said, I came up with something like this:
Group= splitapply(@(v){v}, teamnetworkid.id, findgroups(teamnetworkid.team));
for i=1:numel(Group)
CalculateGroupCentrality(get_adjacency_matrix(graph), cell2mat(Group{i}));
end
but now I'm getting
Cell contents reference from a non-cell array object.
Error in cell2mat (line 42)
cellclass = class(c{1});
So, I guess I need this cell array converted to a line vector?
The proper way to write that loop would be
centrality = zeros(size(Group));
for i = 1:numel(Group)
centrality(i) = CalculateGroupCentrality(get_adjacency_matrix(graph), Group{i});
end
Or you could replace the whole lot by
centrality = cellfun(@(g) CalculateGroupCentrality(get_adjacency_matrix(graph), g), Group);
or even simpler:
centrality = cellfun(callCalulateGroupCentrality, Group);
But if the above work, there's no reason for your original splitapply not to work.
This is great, thank you! Learn something new every single day :)
The problem is that this final call returns:
Error using cellfun
Input #2 expected to be a cell array, was double instead.
This is basically the answer... whatever @Guillaume commented here works just fine. I made a mistake somewhere else and just realized that those methods I've been calling work in some cases but not in other. But is somewhere else. Splitting works just as @Birdman and @Guillaume suggested.

请先登录,再进行评论。

更多回答(1 个)

The error is generated by CalculateGroupCentrality. You should get the same error if you called CalculateGroupCentrality with, for example:
CalculateGroupCentrality(get_adjacency_matrix(graph), [403; 932; 264; 552])
Is the function designed to work with vectors in any direction or is it restricted to row vectors?
To narrow the problem down, you would need to show us the code of that function.

6 个评论

No, that part works just fine. That's why it was strange. When I call the method the way you mentioned, everything is alright.
What is returned by CalculateGroupCentrality in the above case? A scalar value?
Can you share the code of that function?
The way you're using splitapply is correct as long as the function does not error and returns scalar values (regardless of input).
Can you also show the output of
teamnetworkid.id(G == 1)
It does return a scalar value. Unfortunately, I didn't write that function and really not sure if I'm allowed to share.
Anyways, the function works correctly and does return a scalar value.
Could it be that when the anonymous function was created get_adjacency_matrix was a variable rather than a function? Or a different function?
Does callCalculateGroupCentrality(teamnetwork.id(G == 1)) work?
This doesn't work either. So, let's say we have two calls:
CalculateGroupCentrality(get_adjacency_matrix(graph), [403, 932, 264, 552])
and
G = findgroups(teamnetwork.team);
CalculateGroupCentrality(get_adjacency_matrix(graph), teamnetwork.id(G == 1));
where both calls would print the second argument. The output from the first call would be:
403 932 264 552
ans =
6.4890e-06
and for the second one:
403
932
264
552
Subscripted assignment dimension mismatch.
Error in CalculateGroupCentrality (line 32)
A(H,:) = zeros(Vertices2Remove,SizeGraph);
Error in main (line 28)
CalculateGroupCentrality(get_adjacency_matrix(graph), teamnetworkid.Id(G == 1));
Could this be something fairly simple? Just the data type?

请先登录,再进行评论。

类别

在 帮助中心 和 File Exchange 中查找有关 Logical 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by