Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter 'rows' in a Matlab structure

I have structure with 10 fields of the same size. The structure was read from a data file.

dataFile = ezread('myFile','\t');

I get a specific field (double) and produce an index array for all rows which are bigger than 2.

a_field = dataFile.a_field;
a = ismember(a_field,2:1000)

I could use 'a' to get all rows from another field where 'a_field' is bigger than 2. But how can I filter the complete structure? I would like to have a new structure which holds all rows from all fields where 'a_field' is bigger than 2.

It's a basic question, but I can't find an easy way around.

like image 695
Martin Preusse Avatar asked Aug 24 '11 09:08

Martin Preusse


1 Answers

Structures store their fields separately, so you have to go and apply your filter to each.

For example, consider the following structure

%# a sample structure
dataFile.a_field = randn(20,1) + 1;
dataFile.b_field = num2str((1:20)','string %d');  %'
dataFile.c_field = rand(20,1);

%# find rows where 'a_field' is bigger than 2
idx = dataFile.a_field > 2;

Now you have two options to filter the other fields:

1) structfun

use STRUCTFUN to apply your filtering function on each field:

data2 = structfun(@(x) x(idx), dataFile, 'UniformOutput',false);

2) FOR-loop + dynamic field names

write an explicit for-loop, and use dynamic field names to access each:

fn = fieldnames(dataFile);
for i=1:numel(fn)
    data2.(fn{i}) = dataFile.(fn{i})(idx);
end

3) cellarrays

Alternatively, we could convert the stucture to a cellarray, then apply the slicing to the entire thing:

%# cellarray
C = struct2cell(dataFile);
C = [num2cell(C{1}) cellstr(C{2}) num2cell(C{3})];

%# filter rows from all columns
idx = vertcat(C{:,1}) > 2;
C_filtered = C(idx,:)

The result in this case:

>> C_filtered
C_filtered = 
    [3.0034]    ' string 5'    [ 0.53406]
    [2.4158]    'string 11'    [ 0.18971]
    [2.0289]    'string 13'    [ 0.14761]
    [ 2.458]    'string 14'    [0.054974]
    [2.7463]    'string 16'    [ 0.56056]
like image 119
Amro Avatar answered Oct 16 '22 17:10

Amro