计算结构中没有任何NaN的行

时间:2016-02-02 13:48:20

标签: arrays matlab struct

我需要计算结构数组中所有字段中没有任何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的情况下计算结构的最简单方法是什么?

6 个答案:

答案 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

的情况下给出1

答案 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迭代astructfun来迭代字段,您将得到一个没有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