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.
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:
use STRUCTFUN to apply your filtering function on each field:
data2 = structfun(@(x) x(idx), dataFile, 'UniformOutput',false);
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
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With