Moving data within a struct: shifting from one cell to another cell with multiple repetitions.

Hi all,
So my coding/scripting is still very much in development, and while I can usually figure out a solution, this one has me a little stuck.
I'm trying to move data from one cell to a different cell within a strutct that contains multiple fields of repeated condition and item names. With reference to the attached figures, I am trying to copy the data contained in the accuracy cell in the same row as phase('Recog1') and image('GLOCS'), and paste this data in the accuracy cell in the same row as Phase ('Learn1') and Image('Glocs)'. There are six learning and recog conditions and 40 images, for which the order is randomiosed in each learning and recog condition.
I understand that the above description might not make perfect sense, but any help would be greatly appreciated.
Also, please let me know if you need additional info to help answer the question.

Answers (1)

I think I follow your question, a few pro tips:
  • If you can make your question less about your example and more about the abstract question you're trying to solve, that makes it easier to understand the question. The various irrelevant fields in your struct just make it hard to follow!
  • Working with tables is easier than working with structs. Especially with data like what you have here. You can often convert from struct to table with something as simple as struct2table. (on the other hand) I do notice that you've got some mixed type variables, it seems your data is only doing that for empties - the empty double [ ] in a column of chars should maybe be an empty char ' ' which would be much easier to work with.
  • Similarly, working with strings is way easier than working with chars, you can often convert with a simple call to string. (particularly handy and easy on a table variable).
%% Generate some fake data:
s=struct;
s(1).code={'a'};
s(1).type={'moose'};
s(1).accuracy=[];
s(2).code={'b'};
s(2).type={'moose'};
s(2).accuracy=[];
s(3).code={'a'};
s(3).type={'goose'};
s(3).accuracy=42;
s(4).code={'b'};
s(4).type={'horse'};
s(4).accuracy=[];
% Using struct2table just for a preview of what the data look like in my example:
struct2table(s)
ans = 4×3 table
code type accuracy _____ _________ ____________ {'a'} {'moose'} {0×0 double} {'b'} {'moose'} {0×0 double} {'a'} {'goose'} {[ 42]} {'b'} {'horse'} {0×0 double}
%% get the index of elements in the struct as described:
ind_to = strcmp([s.code],'b') & strcmp([s.type],'horse');
ind_from = strcmp([s.code],'a') & strcmp([s.type],'goose');
% do the copying
s(ind_to).accuracy = s(ind_from).accuracy;
% For this to work, ind_from and ind_to must both have found exactly one
% element...while you may know this is true for your data...how does MATLAB
% know this is true? Do you want to check that its true before you proceed
% so that you don't get a weird error (which you might not recognize one
% day)?
% Show the result
struct2table(s)
ans = 4×3 table
code type accuracy _____ _________ ____________ {'a'} {'moose'} {0×0 double} {'b'} {'moose'} {0×0 double} {'a'} {'goose'} {[ 42]} {'b'} {'horse'} {[ 42]}
Here's the table/string version, the table part doesn't make much difference but lets you drop those [ ], and the string part isn't much different but it lets you use == instead of strcmp:
t = struct2table(s);t.code=string(t.code);t.type=string(t.type);
t.accuracy(t.code=="b" & t.type=="moose") = t.accuracy(t.code=="a" & t.type=="goose")
t = 4×3 table
code type accuracy ____ _______ ____________ "a" "moose" {0×0 double} "b" "moose" {[ 42]} "a" "goose" {[ 42]} "b" "horse" {[ 42]}

3 Comments

Hello,
thanks so much for your assistance - really comprehensive. With regard to your question about checking to ensure things are true, it would be great if you could let me know how to do that as well... makes good sense!
Cheers
Also, I took your advice and practiced with the fake data, then tried to apply the solution to my data, but with no success... might this have something to do with the types of variables in my struct (e.g., 'ch')?
For checking things are true, there are maybe two sorts of broad ways to think about it.
The first is: if it's not true, your code should stop, and tell you:
assert(sum(s(ind_from).accuracy)==1, "Expected exactly one source, but didn't find that.")
assert(sum(s(ind_to).accuracy)==1, "Expected exactly one target, but didn't find that.")
An assert says, if the thing isn't true, an error should show up.
The second is, if it's not true do something different:
if sum(s(ind_from).accuracy)>1
% More than one found, so take the first
ind_from = find(ind_from, 1, 'first')
elseif sum(s(ind_from).accuracy)==0
% None found, fill with zeros
s(ind_to).accuracy = 0;
end
WRT 'no success' - did it error? Or did nothing happen? What is the result of sum(ind_from) and sum(ind_to) with your data?

Sign in to comment.

Tags

Asked:

on 10 Aug 2021

Commented:

on 11 Aug 2021

Community Treasure Hunt

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

Start Hunting!