Appending data when extracting nested fields as individual variables
1 view (last 30 days)
Show older comments
Hi Matlab community,
I have a variable "hands" that contains several fields, and I am trying to make hand_type, one of the fields, as an individual variable. The size of "hands" varies between 1x1 struct and 1x2 struct, hence I used the if-elseif loop. When "hands" is 1x2 struct, I want the second group of data to be stored in a parallel cell next to the first group of data, hence the {end+1}, as I don't want them to be in the same cell and create an additional layer of nesting.
However, in the resulting "hand_type", whenever "hands" is 1x2 struct, "hand_type" only has 0x0 double. In comparison, when "hands" is 1x1 struct, "hand_type" has a value of a number (0, 1, etc).
Could someone help me to identify what I am doing wrong, and how I can fix the problem? The full script is attached.
Thank you in advance!
has_hands = ~cellfun(@isempty, {frames.hands});
filtered_frames = frames(has_hands);
id = {filtered_frames.id};
time = {filtered_frames.timestamp};
hands = {filtered_frames.hands};
hand_type = cell(size(hands));
for i = 1:numel(hands)
if isequal(size(hands{i}),[1,1])
hand_type{i} = hands{i}.type;
elseif isequal(size(hands{i}),[1,2])
hand_type{end+1} = hands{i}(1).type;
hand_type{end+1} = hands{i}(2).type;
end
4 Comments
Voss
on 30 Apr 2024
@Julia Thanks for that!
However, it looks like the variable in the .mat file is not similar to what you describe in the question.
S = load('frames.mat')
frames = S.first100
temp = [frames.frames]
any(temp)
It is a struct array with one field (called "frames") containing all scalar zeros, instead of a struct array with multiple fields ("hands", "id", "timestamp").
Accepted Answer
Stephen23
on 1 May 2024
Edited: Stephen23
on 1 May 2024
The simple and efficient MATLAB approach using two comma-separated lists (no loops are required!):
first100 = load('frames.mat').first100
tmp = [first100.hands]; % 1x140 structure array
hand_type = [tmp.type] % 1x140 double array
7 Comments
Stephen23
on 1 May 2024
"For my new variable "thumb_1", I would need all data of "prev_joint" in row 1 for each "bones" structure. However, I am having troubles accessing that."
In total there are 2700 BONES structures: perhaps you only want to access a subset of them.
"Row 1" is confusing me... I do not see any arrays which have more than one row.
first100 = load('frames.mat').first100
tmp = [first100.hands]
digits = [tmp.digits]
id0 = [digits.finger_id]==0;
nnz(id0)
bones = [digits.bones]
[bones.prev_joint]
Perhaps something like this:
thumb = [digits(id0).bones]
or perhaps this, which returns the first element of each structure array:
first = cellfun(@(s)s(1),{digits(id0).bones})
[first.prev_joint]
More Answers (1)
SAI SRUJAN
on 1 May 2024
Edited: SAI SRUJAN
on 1 May 2024
Hi Julia,
I understand that you are facing an issue appending data when extracting nested fields as inidividual variables.
Please go through the following code sample to proceed further,
has_hands = ~cellfun(@isempty, {first100.hands});
filtered_first100 = first100(has_hands);
id = {filtered_first100.id};
time = {filtered_first100.timestamp};
hands = {filtered_first100.hands};
hand_type = {};
for i = 1:numel(hands)
if isequal(size(hands{i}), [1,1])
hand_type{end+1} = hands{i}.type;
elseif isequal(size(hands{i}), [1,2])
hand_type{end+1} = hands{i}(1).type;
hand_type{end+1} = hands{i}(2).type;
end
end
The variable 'hands' is a 1x99 struct, containing 41 structs within it, each of size [1,2]. Therefore, the expected size of 'hand_types' should be 140 double as we are parallelly storing the values instead of nesting.
I hope this helps!
2 Comments
Stephen23
on 1 May 2024
Edited: Stephen23
on 1 May 2024
"The variable 'hands' is a 1x99 struct"
No, it is actually a cell array (not a structure). Lets check it right now (note that MATLAB tells us it is a cell array too):
first100 = load('frames.mat').first100;
has_hands = ~cellfun(@isempty, {first100.hands});
filtered_first100 = first100(has_hands);
hands = {filtered_first100.hands} % <- here you define HANDS as a cell array.
isstruct(hands) % is it a struct array? (hint: no)
iscell(hands) % it is a cell array (exactly as I wrote)
If you had used square brackets it would be a structure array (and more efficient data design).
"containing 41 structs within it, each of size [1,2]."
Lets now check that misinformation as well:
C = cellfun(@size,hands,'uni',0);
unique(vertcat(C{:}),'rows')
Some of the structures are scalar (i.e. 1x1), some have size 1x2 (just as the OP correctly stated).
"Therefore, the expected size of 'hand_types' should be 140 double as we are parallelly storing the values instead of nesting."
But it won't be, because you defined it to be a cell array, not a double array (you can confirm this by actually running your code):
hand_type = {}; % <- cell array
Note that storing lots of scalar numerics in a cell array is very inefficient data design and should be avoided.
See Also
Categories
Find more on Matrix Indexing in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!