2016-02-06 3 views
1

У меня есть таблицаMATLAB: Копирование переменных из таблицы на структуру на основе определенных критериев

column1data = [11; 22; 33]; 
column2data = [44; 55; 66]; 
column3data = [77; 88; 99]; 
rows = {'name1', 'name2', 'name3'}; 
T = table(column1data, column2data, column3data); 
T.Properties.RowNames = rows 


     column1data column2data column3data 
name1  11   44   77 
name2  22   55   88 
name3  33   66   99 

и массив STRUCT

S(1).rownamefield = 'name3'; 
S(2).rownamefield = 'name1'; 
S(3).rownamefield = 'name2'; 
S(1).columnnumberfield = 1; 
S(2).columnnumberfield = 3; 
S(3).columnnumberfield = 2; 
S(1).field3 = []; 
S(2).field3 = []; 
S(3).field3 = []; 

    rownamefield columnnumberfield field3 
1  'name3'   1   [] 
2  'name1'   3   [] 
3  'name2'   2   [] 

структура массива S содержит критерии, необходимые, чтобы выбрать переменную из таблицы T. Как только переменная выбрана, ее необходимо скопировать из таблицы T в пустое поле в структуре S.

S(1).rownamefield содержит имя строки в таблице T, где находится целевая переменная. S(1).columnnumberfield содержит номер столбца в таблице T с целевой переменной. Таким образом, S(1).rownamefield плюс S(1).columnnumberfield являются практически координатами целевой переменной в таблице T. Мне нужно скопировать целевую переменную из таблицы T в поле3 в массиве struct: S(1).field3. Это должно быть сделано для всех структур, поэтому, возможно, это должно быть в цикле for, но я не уверен.

Вывод должен выглядеть следующим образом:

rownamefield columnnumberfield field3 
1  'name3'   1   33 
2  'name1'   3   77 
3  'name2'   2   55 

Я не знаю, как подойти к этой задаче. Это, конечно, упрощенная версия проблемы. Моя реальная таблица данных - 200x200, а массив struct имеет более 2000 структур. Я буду очень признателен за любую помощь в этом.

+0

Нужно ли придерживаться структуры? Вы решаете, как хранить эту информацию. Я лично никогда не использую массивы структуры, такую ​​боль, с которой приходится иметь дело. – Oleg

+0

Я только выяснил, как хранить данные в структурах и таблицах. У меня много наборов данных, поэтому я помещаю их в вложенные структуры. Я не могу поместить таблицу в таблицу (или я могу?), Поэтому мне нужно использовать структуру на каком-то уровне. Мне было легче работать с вложенными структурами, чем с таблицами внутри структур. Возможно, есть еще один способ связать все это вместе, но я не знаю об этом. –

+0

Ваши данные выглядят скалярными, поэтому я не вижу необходимости в структуре вместо таблицы (возможно, ваши реальные данные сложнее) – Oleg

ответ

1
% Extract table data and linearly index it 
tdata = T{:,:}; 
[~,row] = ismember({S.rownamefield}, T.Properties.RowNames); 
col  = [S.columnnumberfield]; 
pos  = sub2ind(size(tdata),rowpos, col); 
val  = tdata(pos); 

% Assign to struct 
for ii = 1:numel(S) 
    S(ii).field3 = val(ii); 
end 

Вместо для цикла, вы можете использовать решение Suever в с deal() для присвоения значений в один присест (должны num2cell(val) первого). Все быстрее и интуитивно.

+0

Олег, ваш код спас меня! Для моей структуры 180 строк требуется меньше секунды для запуска. Код Suever выше занимает 7 минут, и никакие предварительные/параллельные вычисления не помогают ... –

+0

@ArthurTarasov приветствуется. Кстати, у моей матери есть такая же фамилия, и она из Ростова. – Oleg

+0

Маленький мир! Мои родители из Киева –

2

Вы могли бы сделать что-то вроде следующего.

Сначала преобразуйте поля rownamefield и columnnumberfield в ячейки и массивы для использования в качестве показателей для таблицы.

rows = {S.rownamefield}; 
cols = [S.columnnumberfield]; 
subtable = T(rows, cols); 

Это дает квадратную таблицу, в которой затем можно преобразовать в клетку и принять диагональные элементы, которые являются те, что вы заботитесь о.

values = table2cell(subtable); 
values = values(logical(eye(numel(rows)))); 

Тогда это дает массив ячеек значений, соответствующих записей в S. Затем мы можем присвоить им

[S.field3] = deal(values{:}); 

disp([S.field3]) 

    33 77 55 

Это было бы гораздо проще, если бы table был эквивалент sub2ind.

+0

Мне нравится диагональная интуиция, но это также ее слабость из-за масштабируемости. Вы также дали мне хорошую идею для моего [расширенного 'table()' class] (https://github.com/okomarov/tableutils), то есть для реализации 'sub2ind()' – Oleg

+0

@Oleg Определенно может возникнуть проблема с увеличивая размер. – Suever

+0

@Suever Спасибо! Отлично работает –

Смежные вопросы