Question

Given some data - for example (in my case) - like the following tabular

Name  |pos_x|pos_y|pos_z
------------------------
Point1|   .1|   .1|   .2
Point2|  0.0|  0.0|   .1
Middle|   .1|   .2|   .1
Point3|  0.0|    1|  0.0

and maybe after importing that data from excel all values are stored in a cell array (lets call it celldata).
For testing purposes this cell could be created with the line

celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

For this example the cell is of size 4x4.

At the moment I'm creating a structure with the following lines

point.name=char(celldata(:,1));
point.posxyz=cell2mat(celldata(:,2:4));

This results in point size 1x1 Class struct. I'm looking for an efficient way to generate it as point size 4x1 Class struct - thus one element for each line in the tabular above - all with the same inner structure: a name and the coordinates.
I already tried cell2struct, but that is only able to unfold along one dimension without grouping some colums together - as far as I tried.
Further, this is not a duplicate of Preallocate structure of cells in matlab as in this case here, I have many different columns - or maybe even a dynamic count of columns.

Was it helpful?

Solution

cellData = {'Name', 'pos_x', 'pos_y'; 'Harry', 34, 2; 'Bernard', 5, 11}

Then

for col = 1:size(cellData ,2)
    fieldName = cellData{1, col};
    c = cellData (2:end, col);
    [point(1:length(c)).(fieldName)] = c{:};
end

Now

point(1)

ans = 

     Name: 'Harry'
    pos_x: 34
    pos_y: 2

point(2)

ans = 

     Name: 'Bernard'
    pos_x: 5
    pos_y: 11

EDIT:

If you want to only have 2 fields, i.e. Name and posxyz then:

 [M, N] = size(celldata);
 names = celldata(:,1);
 [point(1:M).Name] = names{:};
 xyz = mat2cell(cell2mat(celldata(:,2:end)), ones(M,1), N - 1);
 [point(1:M).posxyz] = xyz{:};

now for celldata={'Point1' .1 .1 .2;'Point2' 0 0 .1;'Middle' .1 .2 .1;'Point3' 0 1 0}

point(1)

ans = 

          Name: 'Point1'
        posxyz: [0.1000 0.1000 0.2000]

point(2)

ans = 

      Name: 'Point2'
    posxyz: [0 0 0.1000]

OTHER TIPS

Try using struct with cell arrays as input:

C = cellfun(@(x,y,z)[x y z], celldata(:,2), celldata(:,3), celldata(:,4), 'Uniform', 0);
point = struct('name', celldata(:, 1), 'posxyz', C);

Notice that for the posxyz field I've created a new cell array by catenating the cells of celldata.

If you want to add another field later, you can use deal and comma-separated lists. The following example stores the values from the fourth column of celldata in a new field, called pos_z:

[point(:).pos_z] = deal(celldata{:, 4});
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top