我需要计算结构数组中所有字段中没有任何NaN的结构数。示例结构如下所示:
a(1).b = 11;
a(2).b = NaN;
a(3).b = 22;
a(4).b = 33;
a(1).c = 44;
a(2).c = 55;
a(3).c = 66;
a(4).c = NaN;
输出看起来像这样
Fields b c
1 44 11
2 55 NaN
3 66 22
4 NaN 33
没有NaN的结构是1和3,所以这里应该总共有2个。
我尝试使用size(a, 2)
,但它只是告诉我数组中的结构总数。我需要它来计算 N (样本中的观察数)。 NaNs不算作观察结果,因为它们在分析中被省略。
在结构数组中没有任何NaN的情况下计算结构的最简单方法是什么?
答案 0 :(得分:7)
我建议使用以下一行命令:
This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi
nnz(~any(cellfun(@isnan,struct2cell(a))))
将您的结构转换为3D单元格数组
struct2cell(a)
将cellfun(@isnan,___)
应用于单元格数组的每个元素
isnan
沿第一维工作,返回没有NaN的数组
~any(__)
计算没有NaN的行数
结果只是一个数字,在这种情况下为nnz(__)
。
以下内容:
2
会告诉你哪些行没有NaN
答案 1 :(得分:5)
这会告诉你哪些没有NaN
for ii=1:size(a,2)
hasNoNaNs(ii)=~any(structfun(@isnan,a(ii)));
end
它的工作方式是迭代每个结构,并使用structfun
在其中的每个元素中调用isnan
,然后检查它们中的any
是否为{ {1}}并否定结果,因此在没有NaN
s
答案 2 :(得分:4)
因为bsxfun
永远不是错误的做法!
sum(all(bsxfun(@le,cell2mat(struct2cell(a)),inf)))
这是如何运作的:
这会将结构转换为单元格,然后转换为矩阵:
cell2mat(struct2cell(a))
ans(:,:,1) =
11
44
ans(:,:,2) =
NaN
55
ans(:,:,3) =
22
66
ans(:,:,4) =
33
NaN
然后它使用bsxfun
来检查哪些元素小于或等于零。唯一不满足此条件的值是NaN
。
bsxfun(@le,cell2mat(struct2cell(a)),inf)
ans(:,:,1) =
1
1
ans(:,:,2) =
0
1
ans(:,:,3) =
1
1
ans(:,:,4) =
1
0
然后,我们检查每个切片中的所有值是否都为真:
all(bsxfun(@le,cell2mat(struct2cell(a)),inf))
ans(:,:,1) =
1
ans(:,:,2) =
0
ans(:,:,3) =
1
ans(:,:,4) =
0
最后,我们总结一下:
sum(all(bsxfun(@le,cell2mat(struct2cell(a)),inf)))
ans =
2
(顺便说一下:它可以跳过bsxfun
,但其中的乐趣在哪里)
sum(all(cell2mat(struct2cell(a))<=inf))
答案 3 :(得分:3)
使用arrayfun
迭代a
和structfun
来迭代字段,您将得到一个没有NaN
s的元素的逻辑数组:
>> arrayfun(@(x) ~any(structfun(@isnan, x)), a)
ans =
1 0 1 0
现在你可以sum
>> sum(arrayfun(@(x) ~any(structfun(@isnan, x)), a))
ans =
2
答案 4 :(得分:2)
将this not working answer的想法用于逗号分隔列表:
s=sum(~any(isnan([[a.b];[a.c]])));
对字段名称进行硬编码可能看起来很愚蠢,但它会导致快速代码,因为它避免了迭代和单元格数组。
将这种方法概括为仲裁字段名称,最终得到了这个解决方案:
n=true(size(a));
for f = fieldnames(a).'
n(isnan([a.(f{1})]))=false;
end
n=sum(n(:));
假设你有一个只有很少字段名的大型结构,这非常有效,因为它只是迭代字段名。
答案 5 :(得分:1)
第三种解决方案可能 - 根据您的数据可能不是很优雅:
A = [[a.b];[a.c]]; %//EDIT -- Fixed based on @Daniel's correct solution
IndNotNaN = find (~isnan(A));
取决于你是否有很多结构,你必须连接a.b,a.c .... a.n