在Matlab中绘制结构数组

时间:2018-01-07 02:19:32

标签: matlab matlab-figure matlab-guide

我在MATLAB中有一个结构数组(98 * 1):

enter image description here

现在我试图通过使用2个特定字段(比如x和y)来绘制图形。 x和y的值存在于这98行中的每一行上。尝试使用以下命令绘制错误。

plot(ans{1:98,1}.x,ans{1:98,1}.y)
  

预期来自大括号或点索引表达式的一个输出,但是   有98个结果。

     

只是(第1行)图中的错误(ans {1:98,1} .x,ans {1:98,1} .y)

需要帮助知道我做错了什么,以及如何纠正它。

2 个答案:

答案 0 :(得分:5)

你可以通过

做你想做的事
S = [ans{:}];
x = [S.x];
y = [S.y];
plot(x,y)

第一行将单元格数组转换为结构数组。 ans{:}返回单元格数组中所有元素的逗号分隔列表。方括号捕获,将所有元素连接到一个向量中。

S.x再次返回以逗号分隔的列表。在这里,我们将所有x值连接到一个数字向量中。

未经请求的建议

但请,请更改您存储数据的方式。下面我将说明为什么你应该这样做。

让我们从类似于你的结构中的一些随机数据开始(每个元素都是结构的单元格数组):

C = cell(1,100);
for ii=1:length(C)
   C{ii} = struct('x',randn(1),'y',randn(1),'z',randn(1),...
      'name',char('a'+floor(rand(1,10)*('z'-'a'+1))),...
      'status',rand(1)>0.3);
end

更好的解决方案是结构数组:

S = [C{:}];

结构数组是MATLAB中的标准事物:它是一个数组,其中每个元素都是相同的结构。你对这两者的索引有所不同:

>> C{5}
ans = 
  struct with fields:
         x: -0.0818
         y: 0.5463
         z: -0.8194
      name: 'ysrkqlzcms'
    status: 1

>> S(5)
ans = 
  struct with fields:
         x: -0.0818
         y: 0.5463
         z: -0.8194
      name: 'ysrkqlzcms'
    status: 1

为什么S是比C更好的解决方案?

结构数组的内存效率更高

>> whos
  Name        Size              Bytes  Class     Attributes
  C           1x100            103700  cell                
  S           1x100             60820  struct              

请注意C的占用率几乎是S的两倍。为什么是这样? C包含100个结构,每个结构存储一些值,但也包含这些值的名称。因此,C存储相同名称的100倍(在这种情况下,'x''y''z''name''status')。 S只存储一次。

结构数组更容易索引。

您需要发布此问题证明了这一点。我的答案的第一步是将单元格数组转换为结构数组。 Luis Mendo的回答显示了使用结构单元格数组是多么尴尬。

结构数组更安全

您可以执行C{5} = 'sorry',并阻止使用任何类型的方法来使用结构的所有x元素,因为其中一个单元格不再是结构体。 S(5)='sorry'给出错误。也就是说,没有办法强制结构的单元格数组中的所有结构都具有相同的元素。这使事情变得非常复杂。

但是还有更好的方法

由于MATLAB R2013b有一个table类。类型table的对象甚至比结构数组更好。

T = struct2table(S);

表将每列存储为单个数组,因此开销较少。也就是说,T.x是一个单独的数组,而不是S.x,它是100个数组。这使得它更有效率:

>> whos
  Name        Size              Bytes  Class     Attributes
  C           1x100            103700  cell                
  S           1x100             60820  struct              
  T         100x5               17476  table               

请注意T如何使用C内存的1/6。这使得它也是类型安全的:每行的x值保证是相同的类型和大小。如果将x定义为标量双精度,则不能将字符串分配给一个x值,也不能将任何非标量赋值。

再次建立索引略有不同,但T.x直接为您提供了所有x值的数组,并且

>> T(5,:)
ans =
  1×5 table
    x           y          z            name        status
_________    _______    ________    ____________    ______
-0.081774    0.54633    -0.81939    'ysrkqlzcms'    true  

所以,不要将C{5}.xS(5).x编入索引,而是T.x(5)

答案 1 :(得分:0)

您可能需要cellfun anonymous function(或for循环)从每个单元格的内容中提取xy字段:

plot(cellfun(@(t) t.x, ans(1:98,1)), cellfun(@(t) t.y, ans(1:98,1)))

注意:

  • ()使用索引而不是{},因为cellfun需要一个单元格数组作为输入(有关索引单元格数组的更多信息here)。此外,如果要处理整个单元阵列,可以完全跳过索引,只需使用

    plot(cellfun(@(t) t.x, ans), cellfun(@(t) t.y, ans))
    
  • 两个匿名函数@(t) t.x@(t) t.y作用于每个单元格的内容,即标量结构,并分别从xy字段中提取。默认情况下,结果按cellfun打包到标准(数字)数组中。

如果您的数据以更方便的方式组织会更容易,例如包含字段xy的98×1结构数组,或者更好的是两个数字向量{{1 }和x