我有一个代表分子状态的长数字矩阵.子集可能如下所示:
states = [...
1 1 1 1
1 1 1 1
1 0 1 1
NaN 0 NaN NaN
1 0 1 0
1 0 1 1
NaN NaN NaN NaN
1 0 1 1
NaN NaN NaN NaN
1 1 0 0
];
Run Code Online (Sandbox Code Playgroud)
其中NaN
值是表示未知的状态.实际上,此列表可能包含数十万个值.如果我使用该unique
命令获取唯一状态,结果看起来像
K>>unique(states,'rows')
ans =
1 0 1 0
1 0 1 1
1 1 0 0
1 1 1 1
NaN 0 NaN NaN
NaN NaN NaN NaN
NaN NaN NaN NaN
Run Code Online (Sandbox Code Playgroud)
因为"独特的将NaN值视为独特".
如何按下此输出以使NaN值不明显?那[NaN NaN NaN NaN]
是不同的[NaN 0 NaN NaN]
但是[NaN NaN NaN NaN] == [NaN NaN NaN NaN]
?
代码
%// Get unique rows with in-built "unique" that considers NaN as distinct
unq1 = unique(states,'rows');
%// Detect nans
unq1_nans = isnan(unq1);
%// Find nan equalities across rows
unq1_nans_roweq = bsxfun(@plus,unq1_nans,permute(unq1_nans,[3 2 1]))==2;
%// Find non-nan equalities across rows
unq1_nonans_roweq = bsxfun(@eq,unq1,permute(unq1,[3 2 1]));
%// Find "universal" (nan or non-nan) equalities across rows
unq1_univ_roweq = unq1_nans_roweq | unq1_nonans_roweq;
%// Remove non-unique rows except the first non-unique match as with
%// the default functionality of MATLAB's in-built unique function
out = unq1(~any(triu(squeeze(sum(unq1_univ_roweq,2)==size(states,2)),1),1),:);
Run Code Online (Sandbox Code Playgroud)
例子#1
输入 -
states =
3.0000 1.0000 7.0000 8.0000
8.0000 0 1.0000 6.0000
Inf 0 NaN NaN
5.0000 0 1.0000 0
Inf 0 NaN NaN
7.0000 0 5.0000 1.0000
NaN NaN 11.2000 Inf
NaN NaN 15.0000 NaN
NaN NaN 11.2000 Inf
Run Code Online (Sandbox Code Playgroud)
使用 MATLAB 内置unique
+ 'rows'
-的中间结果
unq1 =
3.0000 1.0000 7.0000 8.0000
5.0000 0 1.0000 0
7.0000 0 5.0000 1.0000
8.0000 0 1.0000 6.0000
Inf 0 NaN NaN
Inf 0 NaN NaN
NaN NaN 11.2000 Inf
NaN NaN 11.2000 Inf
NaN NaN 15.0000 NaN
Run Code Online (Sandbox Code Playgroud)
请注意,具有相同值的两行 -[Inf 0 NaN NaN]
仍然显示,同样,我们还有另一个相同的对 - [NaN NaN 11.2000 Inf]
。我们需要为这两对中的每一对保留一个唯一的行。让我们看看我们的代码如何执行 -
out =
3.0000 1.0000 7.0000 8.0000
5.0000 0 1.0000 0
7.0000 0 5.0000 1.0000
8.0000 0 1.0000 6.0000
Inf 0 NaN NaN
NaN NaN 11.2000 Inf
NaN NaN 15.0000 NaN
Run Code Online (Sandbox Code Playgroud)
效果还不错!
例子#2
对于最终测试,让我们测试一下输入数组中也有大数字的情况,如下所示 -
states =
3 1 7 8
8 0 1 6
Inf 0 NaN NaN
5 0 1 0
Inf 0 NaN NaN
7 0 5 1
NaN NaN 1e+100 Inf
NaN NaN 15 NaN
NaN NaN 1e+100 Inf
Run Code Online (Sandbox Code Playgroud)
unique
带+的中间结果'rows'
将是 -
unq1 =
3 1 7 8
5 0 1 0
7 0 5 1
8 0 1 6
Inf 0 NaN NaN
Inf 0 NaN NaN
NaN NaN 15 NaN
NaN NaN 1e+100 Inf
NaN NaN 1e+100 Inf
Run Code Online (Sandbox Code Playgroud)
因此,我们的代码必须删除最后两行之一。
out =
3 1 7 8
5 0 1 0
7 0 5 1
8 0 1 6
Inf 0 NaN NaN
NaN NaN 15 NaN
NaN NaN 1e+100 Inf
Run Code Online (Sandbox Code Playgroud)
确实如此!