我需要用前一个元素按行替换矩阵中的零(或 NaN),所以基本上我需要这个矩阵 X
[0,1,2,2,1,0;
5,6,3,0,0,2;
0,0,1,1,0,1]
变成这样:
[0,1,2,2,1,1;
5,6,3,3,3,2;
0,0,1,1,1,1],
请注意,如果第一行元素为零,它将保持原样。
我知道这已经以向量化的方式解决了单个行或列向量,这是最好的方法之一:
id = find(X);
X(id(2:end)) = diff(X(id));
Y = cumsum(X)
问题是 Matlab/Octave 中矩阵的索引是连续的,并且按列递增,因此它适用于单个行或列,但不能应用相同的概念,但需要用多行进行修改,因为每个行raw/column 重新开始,必须被视为独立的。我已经尽了最大努力并搜索了整个谷歌,但找不到出路。如果我在循环中应用同样的想法,它会变得太慢,因为我的矩阵至少包含 3000 行。谁能帮我解决这个问题?
最佳答案
每行中零被隔离的特殊情况
您可以使用 find
的双输出版本来做到这一点在除第一列之外的所有列中找到零和 NaN,然后使用 linear indexing用它们的行前值填充这些条目:
[ii jj] = find( (X(:,2:end)==0) | isnan(X(:,2:end)) );
X(ii+jj*size(X,1)) = X(ii+(jj-1)*size(X,1));
一般情况(每行允许连续零)
X(isnan(X)) = 0; %// handle NaN's and zeros in a unified way
aux = repmat(2.^(1:size(X,2)), size(X,1), 1) .* ...
[ones(size(X,1),1) logical(X(:,2:end))]; %// positive powers of 2 or 0
col = floor(log2(cumsum(aux,2))); %// col index
ind = bsxfun(@plus, (col-1)*size(X,1), (1:size(X,1)).'); %'// linear index
Y = X(ind);
诀窍是利用矩阵aux
,如果X
对应的条目为0且其列号大于1,则包含0;否则包含 2 提升到列号。因此,对该矩阵逐行应用 cumsum
,取 log2
并向下舍入(矩阵 col
)给出最右边的非零条目的列索引直到当前条目,对于每一行(所以这是一种按行的“累积最大”函数。)它只剩下从列号转换为线性索引(使用 bsxfun
;也可以使用 sub2ind
) 并用它来索引 X
。
这仅对中等大小的 X
有效。对于大尺寸,代码使用的 2 的幂很快接近 realmax
并且导致不正确的索引。
例子:
X =
0 1 2 2 1 0 0
5 6 3 0 0 2 3
1 1 1 1 0 1 1
给予
>> Y
Y =
0 1 2 2 1 1 1
5 6 3 3 3 2 3
1 1 1 1 1 1 1
关于matlab - 以完全矢量化的方式用前一个元素逐行或逐列替换矩阵中的零(或 NAN),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21068256/