我有一个名为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
答案 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?并使用阈值进行相等性比较。