【发布时间】:2025-11-22 09:25:02
【问题描述】:
我有 4x2 矩阵 A:
A = [2 NaN 5 8; 14 NaN 23 NaN]';
我想用 A 中每一列中的相关索引替换非 NaN 值。输出如下所示:
out = [1 NaN 3 4; 1 NaN 3 NaN]';
我知道如何手动为每一列执行此操作,但我想要一个自动解决方案,因为我要处理更大的矩阵。有人有任何想法吗?
【问题讨论】:
我有 4x2 矩阵 A:
A = [2 NaN 5 8; 14 NaN 23 NaN]';
我想用 A 中每一列中的相关索引替换非 NaN 值。输出如下所示:
out = [1 NaN 3 4; 1 NaN 3 NaN]';
我知道如何手动为每一列执行此操作,但我想要一个自动解决方案,因为我要处理更大的矩阵。有人有任何想法吗?
【问题讨论】:
out = bsxfun(@times, A-A+1, (1:size(A,1)).');
它是如何工作的:
A-A+1 将A 中的实际数字替换为1,并将NaN 保留为NaN
(1:size(A,1)).' 是行索引的列向量bsxfun(@times, ...) 将上述两者与单例扩展相乘。正如@thewaywewalk 所指出的,在Matlab R2016 及以后的版本中,bsxfun(@times...) 可以替换为.*,因为默认情况下启用了单例扩展:
out = (A-A+1) .* (1:size(A,1)).';
@Dev-Il 建议的替代方案是
out = bsxfun(@plus, A*0, (1:size(A,1)).');
这是可行的,因为乘以 0 会用 0 替换实际数字,并保持 NaN 不变。
【讨论】:
(A-A+1) .* (1:size(A,1)).' 不是吗?
A-A 而不是zeros(...) 非常聪明。不错的代码打高尔夫球。
A-A 给出零 或 NaN 取决于输入:-)
NaN?
mask = find(~isnan(A));
[rows,~] = ind2sub(size(A),mask)
A(mask) = rows;
请注意,ind2sub 的第二个输出需要请求(但 ~ 忽略)以及 [rows,~] 以表明您需要二维矩阵的输出。
A =
1 1
NaN NaN
3 3
4 NaN
A.' =
1 NaN 3 4
1 NaN 3 NaN
还要小心使用两个不同的转置运算符' 和.'。
[n,m] = size(A);
B = ndgrid(1:n,1:m);
B(isnan(A)) = NaN;
甚至(Luis Mendo 的一点启发)
[n,m] = size(A);
B = A-A + ndgrid(1:n,1:m)
或一行
B = A-A + ndgrid(1:size(A,1),1:size(A,2))
【讨论】:
[rows,cols] = find(~isnan(A)); A(sub2ind(size(A), rows, cols)) = rows;
A./A 为 0,NaN 为 NaN。
1:B = A-A + ndgrid(1:n,1:m) :-)
我添加另一个答案有几个原因:
kron *ahem*) 很有趣。A*0与A-A的作用相同。A = [2 NaN 5 8; 14 NaN 23 NaN].';
out = A*0 + kron((1:size(A,1)).', ones(1,size(A,2)))
out =
1 1
NaN NaN
3 3
4 NaN
【讨论】: