Use of arrayfun and sprintf to order data

Hi, I have a 1x4cell (files) with 1x1struct in each cell. Each structure contains several variables. I would like to extract from each structure only the variables called: SL_X_Y, where X can be numbers from 1 to 7 and Y could be numbers from 1 to 3 i.e. SL_5_2. Not all the combinations are found in each structure. The resulting 1x4cell will only contain structures with the variables SL_X_Y that are found.
Thanks

2 comentarios

Andrei Bobrov
Andrei Bobrov el 26 de Sept. de 2016
Editada: Andrei Bobrov el 26 de Sept. de 2016
Attach your data.  
 
Isma_gp
Isma_gp el 27 de Sept. de 2016
An example file attached

Iniciar sesión para comentar.

 Respuesta aceptada

Guillaume
Guillaume el 27 de Sept. de 2016
Editada: Guillaume el 27 de Sept. de 2016
1. Create a function to filter the relevant fields of the structure:
function filtered = filterstruct(unfiltered)
%FILTERSTRUCT: keep only the fields of the structure which match SL_X_Y with X integer between 1 and 7 and Y integer between 1 and 3
fn = fieldnames(unfiltered); %list of all fields
toremove = cellfun(@isempty, regexp(fn, '^SL_[1-7]_[1-3]$', 'once')); %which fields do not match?
filtered = rmfield(unfiltered, fn(toremove)); %get rid of non matching fields
end
2. Apply cellfun:
cellfun(@filterstruct, yourcellarray, 'UniformOutput', false)
Note however, that it appears you use the variable names to store metadata about the variable content, which is not a good idea and the reason you're struggling. Better would have been to have just one SL field which is a 7x3 cell array / matrix. Extraction would have been trivial then.
edit: typo in the regex

4 comentarios

Isma_gp
Isma_gp el 27 de Sept. de 2016
The data is coming in this format. It would be good to have a SL 7x3 cell array. However, I would need to organize the data in this array according to the variable names i.e. SL_2_3 data would go into row 2 column 3 cell in my 7x3 array. Can you help with that?
Thanks
This function would convert a struct with SL_X_Y fields into a 2D cell array:
function out = convert2cell(in)
%Convert input structure with fields SL_X_Y into 2D cell array
%X is an integer between 1 and 7 and indicates the cell row
%Y is an integer between 1 and 3 and indicates the cell column
validateattributes(in, {'struct'}, {'scalar', 'nonempty'}, 1); %only support scalar structures. Could be extended to structure arrays
fn = fieldnames(in);
rc = cellfun(@str2double, regexp(fn, '^SL_([1-7])_([1-3])$', 'tokens', 'once'), 'UniformOutput', false);
assert(~any(cellfun(@isempty, rc)), 'structure contains non SL_X_Y fields');
rc = vertcat(rc{:});
in = struct2cell(in); %convert struct into cell array
out = cell(7, 3);
out(sub2ind(size(out), rc(:, 1), rc(:, 2))) = in;
end
You can then pass this to cellfun:
newc = cellfun(@convert2cell, yourfilteredcellarray, 'UniformOutput', false)
And convert the cell array of cell arrays into a 3D array:
newc = cat(3, newc{:})
Isma_gp
Isma_gp el 27 de Sept. de 2016
Editada: Isma_gp el 27 de Sept. de 2016
I have some troubles to make it work. I'm attaching an example of the input file. I would like a 7x3 cell array containing the SLAM_SH10_X_Y variables in the right cell (X=row Y=column), for each of the four structures.
Thanks
Of course, it doesn't work. In each function, the regular expression is looking for the pattern 'SL_X_Y' (as you originally stated), not 'SLAM_SH10_X_Y'. In addition, the X and Y limits don't match what you said (X goes up to 5, Y goes up to 7).
You need to change the regular expression accordingly.
This will do the filtering and transformation into a cell array. I've removed any restriction on the magnitude of X and Y. The cell array will be as big as necessary.
function filtered = filtertocell(unfiltered)
%FILTERTOCELL: filter a structure to only keep fields SLAM_SH10_X_Y and convert fields to 2D cell array
%X and Y are integers indicating the row, column respectively of the destination cell
validateattributes(unfiltered, {'struct'}, {'scalar', 'nonempty'});
fn = fieldnames(unfiltered);
rc = cellfun(@str2double, regexp(fn, '^SLAM_SH10_(\d+)_(\d+)$', 'tokens', 'once'), 'UniformOutput', false);
unshapedfiltered = struct2cell(rmfield(unfiltered, fn(cellfun(@isempty, rc))));
rc = vertcat(rc{:});
filtered = cell(max(rc));
filtered(sub2ind(size(filtered), rc(:, 1), rc(:, 2))) = unshapedfiltered;
end
cellfun(@filtertocell, files, 'UniformOutput', false)

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Preguntada:

el 26 de Sept. de 2016

Comentada:

el 27 de Sept. de 2016

Community Treasure Hunt

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

Start Hunting!

Translated by