MATLAB:用NaN替换每列的前导零

时间:2018-09-05 08:07:34

标签: matlab for-loop vectorization

我有一个名为mat的3D矩阵。每列可以包含或可以不包含可变数量的前导零。我需要用NaN代替它们。重要的是要认识到,在第一个非零元素出现之后,任何列中都可能跟随着更多的零。也就是说,仅索引矩阵中的所有零并将其替换为NaN不会导致正确的结果。

我有一个可行的解决方案。但是,它包含两个for循环。我想知道是否有可能进行向量化并摆脱循环。实际上,mat可能很大,例如10000x15x10000。因此,我对执行速度非常敏感。

这是我的玩具示例:

% Create test matrix
mat = randi(100,20,5,2);
mat(1:5,1,1) = 0;
mat(1:7,2,1) = 0;
mat(1:3,4,1) = 0;
mat(1:10,5,1) = 0;
mat(1:2,1,2) = 0;
mat(1:3,3,2) = 0;
mat(1:7,4,2) = 0;
mat(1:4,5,2) = 0;

% Find first non-zero element in every column
[~, firstNonZero] = max( mat ~= 0 );

% Replace leading zeros with NaN
% How to vectorize this part???
[nRows, nCols, nPlanes] = size(mat);
for j = 1 : nPlanes

   for i = 1 : nCols

       mat(1:firstNonZero(1, i, j)-1, i, j) = NaN;

   end

end

1 个答案:

答案 0 :(得分:5)

您可以使用cumsum在每一列下创建一个累加总和,然后所有前导零的累加总和为零,而所有中间零的累加总和都大于零...

mat( cumsum(mat,1) == 0 ) = NaN;

如评论中所建议,如果您的mat为负值,那么以后累积的总和将为0 ...改用绝对值之和

mat( cumsum(abs(mat),1) == 0 ) = NaN;

请注意,默认情况下,cumsum沿第一个非单维度运行,您可以使用可选的dim参数指定维度。如果您的dim=1的高度为1,我已经使用mat强制执行列式操作,但这是任何高度大于1的矩阵的默认设置。

请注意,这使用==进行比较,您可能需要阅读Why is 24.0000 not equal to 24.0000 in MATLAB?并使用阈值进行相等性比较。