Appending data when extracting nested fields as individual variables
1 vue (au cours des 30 derniers jours)
Afficher commentaires plus anciens
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 commentaires
Voss
le 30 Avr 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").
Réponse acceptée
Stephen23
le 1 Mai 2024
Modifié(e) : Stephen23
le 1 Mai 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 commentaires
Stephen23
le 1 Mai 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]
Plus de réponses (1)
SAI SRUJAN
le 1 Mai 2024
Modifié(e) : SAI SRUJAN
le 1 Mai 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 commentaires
Stephen23
le 1 Mai 2024
Modifié(e) : Stephen23
le 1 Mai 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.
Voir également
Catégories
En savoir plus sur Matrix Indexing dans Help Center et File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!