2012-02-12 67 views
2

%实例结构在MATLAB

clear all 
a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 

假装结构表示其中,a1表示 第一个第5天(例如),a2表示5-10天等等... I”时间系列m试图 结合结构中的每个字段名,以便我有一个连续的系列(而不是将它们拆分成不同的结构,例如...

data1 = [a1.data1; a2.data1; a3.data1 ; a4.data1];

and th对数据2和数据3做同样的事情

这样做的最好方法是什么?

回答

7

最好的方法是定义结构作为结构数组事先:

a(1) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a(2) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a(3) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
a(4) = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 

,让你得到的数据很容易:

cat(1,a.data1) 

但是,如果你坚持使用N个结构,然后试试这个:

function so3 
    a1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
    a2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
    a3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
    a4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 

    s{1} = struct2cell(a1); 
    s{2} = struct2cell(a2); 
    s{3} = struct2cell(a3); 
    s{4} = struct2cell(a4); 

    N = numel(fieldnames(a1)); 
    data = cell([1 N]); 
    for i=1:N 
     data{i} = cell2mat(cellfun(@(x){x{i}'},s)); 
    end 

end 
2

@Andrey说得对,“最好的方法是定义结构预先作为结构阵列“。他的答案是完整的。但是我忍不住给出了下面更紧凑的代码来处理“坚持使用N结构”的情况。它假设他们的名字都以foo开头,并以数字结尾,例如。 foo1,foo2,foo21,并且它将导致数据字段相对于foo名称按字母顺序堆叠。

% first make some data 
foo1 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
foo2 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
foo3 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 
foo4 = struct('data1',rand(12,2),'data2',rand(12,2),'data3',rand(12,3)); 

现在,我们在工作区中,随着一些数foo和月底开始的变量的列表,并把它们放入一个单元格,然后我们EVAL该小区的逗号分隔的级联,设置FOO到是这个价值。

varstarter = 'foo'; 
varlist = who('-regexp', ['^' varstarter '[0-9]+']); 
try 
    eval([varstarter '=[' sprintf('%s,',varlist{:}) '];']); 
catch 
    warning('Could not concatenate variables starting with "%s".',varstarter); 
end 

这让我们使用@安德烈的回答直接:

data1 = cat(1, foo.data1); 
data2 = cat(1, foo.data2); 
data3 = cat(1, foo.data3); 

编辑(编):您可以通过foo和分配变量的字段名称循环自动完成这个最后的步骤多一点与同名的同名。如果你想要不同的名字,代码不难修改。也可以添加一个检查来确定这个东西实际上有字段。

if ~isstruct(foo) 
    warning('Variable "%s" is of an unexpected type.',varstarter); 
else 
    varfields = fieldnames(foo); 
    for k=1:length(varfields) 
     eval([varfields{k} '=cat(1, ' varstarter '.' varfields{k} ');']); 
    end 
end 

在避免显式循环的精神,因为它的乐趣,这里是位等效代码else语句的内部:

varfields = repmat(fieldnames(foo)',2,1); 
eval(sprintf(['%s=cat(1,' varstarter '.%s);'],varfields{:})); 
+0

+1 - 真好看!也许你应该添加一个case来检查变量中的数据是否确实是预期的。一种防守性编程。 – 2012-02-12 21:49:00

+0

很棒的回答。由此可以用循环完成最后阶段。因此,首先使用'fieldnames'来查找数组的名称,然后为每个数组生成一个类似于上面所示的变量? – Emma 2012-02-13 11:24:52

+0

@Andrey谢谢。我在串联中添加了一个catch,并且在新的“提取自动化”部分中,我在查找字段之前检查并确定它是一个结构。 – 2012-02-13 15:31:38