MATLAB создание вектора структуры

Учитывая некоторые данные - например (в моем случае) - как следующую табличную

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

и, возможно, после импорта этих данных из Excel все значения сохраняются в массиве ячеек (давайте назовем его celldata).
В целях тестирования эту ячейку можно создать со строкой

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

Для этого примера ячейка имеет размер 4x4.

На данный момент я создаю структуру со следующими строками

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

Это приводит к point size 1x1 Class struct. Я ищу эффективный способ сгенерировать его как point size 4x1 Class struct — таким образом, один элемент для каждой строки в таблице выше — все с одной и той же внутренней структурой: имя и координаты.
Я уже пробовал cell2struct, но это только насколько я пытался разворачиваться по одному измерению без группировки некоторых столбцов.
Кроме того, это не дубликат Предварительно выделить структуру ячеек в Matlab, как в данном случае, у меня есть много разных столбцов - или, может быть, даже динамическое количество столбцов.


person Bastian Ebeling    schedule 29.04.2013    source источник
comment
Как вы думаете, dataset будет чем-то полезен?   -  person fpe    schedule 29.04.2013
comment
Я думаю, было бы неплохо зациклиться на элементах: for punkt=point,disp([punkt.name ':' num2str(norm(punkt.posxyz))]),end в качестве примера. Особо не нужно проверять, сколько элементов. Вы знаете что-нибудь лучше?   -  person Bastian Ebeling    schedule 29.04.2013


Ответы (2)


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

потом

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

Сейчас

point(1)

ans = 

     Name: 'Harry'
    pos_x: 34
    pos_y: 2

point(2)

ans = 

     Name: 'Bernard'
    pos_x: 5
    pos_y: 11

ИЗМЕНИТЬ:

Если вы хотите иметь только 2 поля, то есть Name и posxyz, тогда:

 [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{:};

теперь для 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]
person Dan    schedule 29.04.2013
comment
Спасибо @Dan за эту идею, но мне очень не нравится необходимость присваивать имена (например) одно за другим. Пожалуйста, подумайте о таблице с несколькими сотнями или более строками. Дальнейшие идеи? - person Bastian Ebeling; 29.04.2013
comment
Добавление, конечно, можно сделать так же, как в rmfield.m, но я думаю, что это должно быть возможно быстрее, или? - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling сотни строк или сотни столбцов? - person Dan; 29.04.2013
comment
Привет Дэн, в моем комментарии я упоминаю сотни строк. Но (как и в моем последнем редактировании, которое вы, возможно, не видели) также может быть много столбцов. - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling Ну, строки, очевидно, не проблема, просто замените 4 на length(C) для столбцов, я думаю, вам лучше всего подойдет простой цикл for, поэтому, если col является переменной цикла, а C = celldata{:, col}, то [point(1:length(C), col).(C{1})] = C{2:end} - person Dan; 29.04.2013
comment
В своем программировании я всегда стараюсь не использовать циклы for. В моих строках выше нет необходимости в цикле for или проверке длины. Ваши последние примеры для столбцов не работают в R2013a. - person Bastian Ebeling; 29.04.2013
comment
давайте продолжим это обсуждение в чате - person Bastian Ebeling; 29.04.2013

Попробуйте использовать struct с массивами ячеек в качестве входных данных:

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

Обратите внимание, что для поля posxyz я создал новый массив ячеек, объединив ячейки celldata.

Если вы хотите добавить еще одно поле позже, вы можете использовать deal и списки, разделенные запятыми. В следующем примере значения из четвертого столбца celldata сохраняются в новом поле с именем pos_z:

[point(:).pos_z] = deal(celldata{:, 4});
person Eitan T    schedule 29.04.2013
comment
Спасибо, это действительно хорошая идея. В моем случае столбцов гораздо больше, и для удобочитаемости я хотел добавить каждый столбец (или пару столбцов, как в xyz) в одну строку исходного кода. Знаете ли вы, как добавить поля в созданную точечную структуру? - person Bastian Ebeling; 29.04.2013
comment
@BastianEbeling Конечно. Вам нужно будет использовать deal и списки, разделенные запятыми. Смотрите пересмотренный ответ. - person Eitan T; 29.04.2013