1
votes

I was under the impression that structure in matlab were similar to query tables in sql but I have a feeling I might be wrong.

I have a rather large dataset consisting of many entries and many fields. Ideally I want to index the structure, pulling out only the data I am interested in. Here is an example of the dataset

Cond       Type   Stime    ETime
    2       10      1       900
    2       10      1       900
    2       10      1       900
    3       1       901     1800
    3       1       901     1800
    4       1       1801    2700
    8       1       901     1800
    8       1       901     1800
    9       1       901     1800
    9       1       901     1800
    12      1       901     1800
    12      1       901     1800
    13      10      1       900
    13      10      1       900
    13      10      1       900
    16      1       901     1800
    16      1       901     1800
    17      10      1       900
    17      10      1       900
    17      10      1       900
    19      10      1       900
    19      10      1       900
    19      10      1       900
    20      10      1       900
    20      10      1       900
    20      10      1       900
    22      1       901     1800
    22      1       901     1800
    25      10      1       900
    25      10      1       900
    25      10      1       900
    27      1       901     1800
    27      1       901     1800
    28      1       901     1800
    28      1       901     1800
    30      1       1801    2700
    31      1       901     1800
    31      1       901     1800
    32      10      1       900
    32      10      1       900
    32      10      1       900
    35      10      1       900
    35      10      1       900
    35      10      1       900

What I want to do is pull specific data entries for analysis example being I want all entries where Type is equal to 10 or I want all Cond from 1:20 that have ETime == 900.

I can do this by the following

idx = find([stats.Type] == 10);
[stats(idx).Stime]

but for multiple types I need a for loop as trying to use a vector throws an error.

idx = find([stats.Type] == 1:10); % Does not work


% must use this
temp = [];
for aa = 1:10
    idx = find([stats.Type] == aa);
    temp = horzcat(idx,temp);
end
[stats(temp).Stime]

Is this the wrong way to use structures? Is there an easier method to index a structure to pull data of interest?

1
If you use struct2table then you can interact with it as a table, which is generally much more intuitive. - Wolfie
Should I output my data as a table instead of a structure than? I was using structures as I thought of them as querytable esque. - Hojo.Timberwolf
Structures are useful if your fields have different numbers of elements (i.e. you couldn't form a consistent height table). In almost all other areas, I find tables are easier to use. With tables you can use logical indexing, sorting, "join" operations, etc. You can also use dot notation for accessing table columns by name, as you do for accessing struct fields, or select multiple columns by name using myTable( :, {'col1','col2'} ). You don't need weird syntactic tricks like [stats.Type] to group outputs, you can just do stats.Type. - Wolfie
ismember is also a pretty solid catch-all for filtering on multiple values. - Wolfie
Indeed, find(ismember([stats.Type],1:10)); is what you are looking for. Also, you may rely on logical selection rather than indexing, so the find is not necessary in that simple case : [stats(ismember([stats.Type],1:10)).Stime] - Brice

1 Answers

1
votes

This answer proposes using table indexing instead of struct indexing, which is a bit of a side-step to directly answering the question. However, my comments on this post were deemed useful so I've formalised as an answer...


If you use struct2table then you can interact with it as a table, which is generally much more intuitive.

Structures are useful if your fields have different numbers of elements (i.e. you couldn't form a consistent height table). In almost all other areas, I find tables are easier to use.

With tables you can use:

  • Logical indexing

  • Sorting (including sortrows by column name)

  • The family of "join" operations

  • Dot notation for accessing table columns by name, as you do for accessing struct fields, or select multiple columns by name using myTable( :, {'col1','col2'} ). - You don't need weird syntactic tricks like [stats.Type] to group outputs, you can just do stats.Type

I would then use ismember to compare multiple items against a table column...

idx = ismember( stats.Type, 1:10 );

Unless you need the indices, you can skip using find for speed, and just directly index using idx.