我在MatLab中有一个结构数组(98*1):
现在我正试着用两个特定的字段(比如x和y)来绘制一张图。X和y的值出现在这98行中的每一行上。尝试使用以下命令绘制时出错。
plot(ans{1:98,1}.x,ans{1:98,1}.y)
大括号或点索引表达式应该有一个输出,但有98个结果。Just(行1)绘图错误(ANS{1:98,1}.x,ANS{1:98,1}.y)我需要帮助知道我做错了什么,以及如何改正它。
nvbavucw1#
你可以通过以下方式做你想做的
S = [ans{:}]; x = [S.x]; y = [S.y]; plot(x,y)
第一行将单元数组转换为结构数组。ans{:}返回单元格数组中所有元素的逗号分隔列表。方括号捕捉到了这一点,将所有元素连接到一个向量中。S.x再次返回逗号分隔的列表。在这里,我们将所有x值连接到一个数值向量中。
ans{:}
S.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更好的解决方案?
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只存储一次。
'x'
'y'
'z'
'name'
'status'
你需要发布这个问题就证明了这一点。在我的回答中,第一步是将单元数组转换为结构数组。Luis Mendo的回答显示了使用结构的单元格数组是多么尴尬。
您可以使用C{5} = 'sorry',并防止任何使用结构的所有x元素的方法,因为其中一个单元格不再是结构。S(5)='sorry'出现错误。这就是说,没有办法强制结构的单元数组中的所有结构都具有相同的元素。这让事情变得非常复杂。
C{5} = 'sorry'
x
S(5)='sorry'
从MatLab R2013b开始,有一个table类。table类型的对象甚至比结构数组更好。
table
T = struct2table(S);
表将每列存储为单个数组,因此开销要小得多。也就是说,T.x是单个数组,而不是S.x是100个数组。这使它变得非常、非常高效:
T.x
>> 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
>> T(5,:) ans = 1×5 table x y z name status _________ _______ ________ ____________ ______ -0.081774 0.54633 -0.81939 'ysrkqlzcms' true
所以不是索引C{5}.x或S(5).x,而是索引T.x(5)。
C{5}.x
S(5).x
T.x(5)
oyjwcjzk2#
您可能需要cellfun和anonymous function(或for循环)来从每个单元格的内容中提取x和y字段:
cellfun
for
y
plot(cellfun(@(t) t.x, ans(1:98,1)), cellfun(@(t) t.y, ans(1:98,1)))
注:
()
{}
plot(cellfun(@(t) t.x, ans), cellfun(@(t) t.y, ans))
@(t) t.x
@(t) t.y
如果您的数据以一种更方便的方式组织起来,就会容易得多,比如一个带有字段x和y的98×1结构数组,或者更好的方法是使用两个数值向量x和y。
mklgxw1f3#
我曾经遇到过嵌套结构数组的这个问题(例如,我想绘制一种ans.x.y.z)我在我的matlab文件交换中发布了一些简单的定制函数:[1]:https://www.mathworks.com/matlabcentral/fileexchange/116130-matlab-struct-operations你可以用下面的句子来回答这个问题
plotStructArray(ans,'x')
3条答案
按热度按时间nvbavucw1#
你可以通过以下方式做你想做的
第一行将单元数组转换为结构数组。
ans{:}
返回单元格数组中所有元素的逗号分隔列表。方括号捕捉到了这一点,将所有元素连接到一个向量中。S.x
再次返回逗号分隔的列表。在这里,我们将所有x值连接到一个数值向量中。主动请教
但请,请,请更改您存储数据的方式。下面我会为你为什么应该这样做做一个解释。
让我们从类似于您的结构(每个元素都是结构的单元格数组)中的一些随机数据开始:
更好的解决方案是结构数组:
结构数组是MatLab中的标准元素:它是一个数组,其中每个元素都是一个相同的结构。您对这两个索引的索引略有不同:
为什么
S
是比C
更好的解决方案?结构数组在内存方面要高效得多
请注意,
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.x
是单个数组,而不是S.x
是100个数组。这使它变得非常、非常高效:请注意
T
如何使用C
的1/6内存。这也使其类型安全:保证每行的x
值具有相同的类型和大小。如果将x
定义为标量双精度值,则不能将字符串分配给一个x
值,也不能为非标量的任何值分配字符串。再次建立索引略有不同,但是
T.x
直接为您提供所有x
值的数组,并且所以不是索引
C{5}.x
或S(5).x
,而是索引T.x(5)
。oyjwcjzk2#
您可能需要
cellfun
和anonymous function(或for
循环)来从每个单元格的内容中提取x
和y
字段:注:
()
索引而不是{}
,因为cellfun
需要单元格数组作为输入(有关索引单元格数组here的详细信息)。此外,如果您想要处理整个单元格数组,您可以完全跳过索引,只使用@(t) t.x
和@(t) t.y
作用于每个单元格的内容,即标量结构,并分别从中提取x
或y
字段。默认情况下,结果由cellfun
打包到标准(数字)数组中。如果您的数据以一种更方便的方式组织起来,就会容易得多,比如一个带有字段
x
和y
的98×1结构数组,或者更好的方法是使用两个数值向量x
和y
。mklgxw1f3#
我曾经遇到过嵌套结构数组的这个问题(例如,我想绘制一种ans.x.y.z)
我在我的matlab文件交换中发布了一些简单的定制函数:[1]:https://www.mathworks.com/matlabcentral/fileexchange/116130-matlab-struct-operations
你可以用下面的句子来回答这个问题