0

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.

2
  • do you think that dataset would be any helpful? Commented Apr 29, 2013 at 8:40
  • I think it would be fine for looping over the elements: for punkt=point,disp([punkt.name ':' num2str(norm(punkt.posxyz))]),end as an example. Especially one does not need to check how many elements there are. Do you know anything better? Commented Apr 29, 2013 at 8:50

2 Answers 2

1
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]
Sign up to request clarification or add additional context in comments.

7 Comments

Thanks @Dan for this idea, but I really don't like the need to assign the names (for example) one by another. Please think about a table with some hundreds or more lines. Further ideas?
Adding could of course be done like done within rmfield.m - but I think this should be possible some faster, or?
@BastianEbeling hundreds of lines or hundreds of columns?
Hi Dan, in my comment I ment hundreds of lines. But (as in my last edit, which you might not have seen) there could also occur many columns.
@BastianEbeling Well lines obviously isn't a problem, just replace the 4 with length(C), for the columns, I think your best bet is a simple for loop, so if col is the loop variable and C = celldata{:, col} then [point(1:length(C), col).(C{1})] = C{2:end}
|
1

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});

2 Comments

Thank you, this is a really fine idea. In my case there are many more columns - and for readability I wanted to add each column (or pair of columns like in xyz) in one source-code line. Do you know a way to add fields to your created point-structure?
@BastianEbeling Of course. You'll need to use deal and comma-separated lists. See the revised answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.