FriskyGrub
FriskyGrub

Reputation: 1049

Using a string to refer to a structure array - matlab

I am trying to take the averages of a pretty large set of data, so i have created a function to do exactly that. The data is stored in some struct1.struct2.data(:,column) there are 4 struct1 and each of these have between 20 and 30 sub-struct2 the data that I want to average is always stored in column 7 and I want to output the average of each struct2.data(:,column) into a 2xN array/double (column 1 of this output is a reference to each sub-struct2 column 2 is the average)

The omly problem is, I can't find a way (lots and lots of reading) to point at each structure properly. I am using a string to refer to the structures, but I get error Attempt to reference field of non-structure array. So clearly it doesn't like this. Here is what I used. (excuse the inelegence)

function [avrg] = Takemean(prefix,numslits)
% place holder arrays
avs = [];
slits = [];
% iterate over the sub-struct (struct2)
for currslit=1:numslits
    dataname = sprintf('%s_slit_%02d',prefix,currslit);
    % slap the average and slit ID on the end
    avs(end+1) = mean(prefix.dataname.data(:,7));
    slits(end+1) = currslit;
end
% transpose the arrays
avs = avs';
slits = slits';
avrg = cat(2,slits,avs); % slap them together

It falls over at this line avs(end+1) = mean(prefix.dataname.data,7); because as you can see, prefix and dataname are strings. So, after hunting around I tried making these strings variables with genvarname() still no luck!

I have spent hours on what should have been 5min of coding. :'(

Edit: Oh prefix is a string e.g. 'Hs' and the structure of the structures (lol) is e.g. Hs.Hs_slit_XX.data() where XX is e.g. 01,02,...27

Edit: If I just run mean(Hs.Hs_slit_01.data(:,7)) it works fine... but then I cant iterate over all of the _slit_XX

Upvotes: 0

Views: 361

Answers (2)

Eitan T
Eitan T

Reputation: 32930

If you simply want to iterate over the fields with the name pattern <something>_slit_<something>, you need neither the prefix string nor numslits for this. Pass the actual structure to your function, extract the desired fields and then itereate them:

function avrg = Takemean(s)

    %// Extract only the "_slit_" fields
    names = fieldnames(s);
    names = names(~cellfun('isempty', strfind(names, '_slit_')));

    %// Iterate over fields and calculate means
    avrg = zeros(numel(names), 2);
    for k = 1:numel(names)
        avrg(k, :) = [k, mean(s.(names{k}).data(:, 7))];
    end

This method uses dynamic field referencing to access fields in structs using strings.

Upvotes: 2

Dennis Jaheruddin
Dennis Jaheruddin

Reputation: 21561

First of all, think twice before you use string construction to access variables.

If you really really need it, here is how it can be used:

a.b=123;
s1 = 'a';
s2 = 'b';
eval([s1 '.' s2])

In your case probably something like:

Hs.Hs_slit_01.data= rand(3,7);
avs = [];

dataname = 'Hs_slit_01';
prefix = 'Hs';

eval(['avs(end+1) = mean(' prefix '.' dataname '.data(:,7))'])

Upvotes: 0

Related Questions