3

我在循环中有一个矩阵,它是

m=


 -132.5901    -137.2695   -114.1264   -131.4986   -134.5733       Inf
       Inf       Inf       Inf        -135.2631   -121.7322       -119.7471
 -132.7978    -123.8068   -135.9385       Inf      -134.1602     -117.6997
 -130.1930    -134.0093   -137.4125   -128.7641       Inf        -116.0473

我想要一个可以在循环中使用的命令来得到答案:

 -132.5901 -137.2695 -114.1264 -131.4986 -134.5733  -119.7471  
 -132.7978 -123.8068 -135.9385 -135.2631 -121.7322  -117.6997
 -130.1930 -134.0093 -137.4125 -128.7641 -134.1602  -116.0473

我不想要使用 isfinite 命令的单个向量。矩阵大小应使用 Matlab 自动保留。

4

2 回答 2

5

我将假设在保留原始矩阵的大小时,您希望我们用 填充解决方案矩阵的底部NaN。我还将假设Inf任何给定的列中可能有不止一个。在这种情况下,以下基于循环的解决方案对我有用:

%# Set up an example matrix
M = [Inf 2 Inf 4; 5 Inf 6 7; Inf Inf 8 Inf];
[T, N] = size(M);

%# Get an index of finite elements
I1 = isfinite(M);

%# Solution 1
Soln1 = NaN(T, N);
for n = 1:N
    CurCol = M(:, n);
    Soln1(1:sum(I1(:, n)), n) = CurCol(I1(:, n));
end

对于一般情况,这个问题可能有一个完全矢量化的解决方案(肯定有 - 请参阅下面的更新)。但是,如果它比基于循环的解决方案产生了很大的加速,我会感到惊讶。如果您设置了问题,那么现在在 Matlab 中单循环非常快,因此您可以对矩阵的列(而不是行)进行操作,因为这些元素是在内存中按顺序分配的。

现在,让我们假设Inf每列只有一个。在这种情况下,问题更容易解决,可以使用以下单行代码完成:

%# Solution 2
Soln2 = [reshape(M(isfinite(M)), T-1, N); NaN(1, N)];

对于我设置的示例矩阵,解决方案 2 显然会失败,因为无法将 6 个元素重新排列为 T-1 × N(即 2 × 4)矩阵。

更新:好的,所以没有充分的理由,没有循环我无法做到这一点让我很恼火。因此,这是一个无循环的解决方案:

%# Solution 3
Soln3 = NaN(T, N);
I2 = bsxfun(@plus, cumsum(isfinite(M)), (0:T:T*(N-1)));
I2 = I2(:);
I2(I1 == 0) = [];
Soln3(I2) = M(isfinite(M));

循环与非循环解决方案的快速(非常)非严格速度测试:

Elapsed time is 0.203997 seconds.
Elapsed time is 0.251969 seconds.

M尽管 if更大,但非循环解决方案可能会有所改善(相对而言) 。

现在我需要回去工作了:-)

于 2012-11-26T06:55:06.453 回答
2

基于 Colin 的回答:

>> M = [Inf 2 Inf 6; 5 Inf 8 4; Inf Inf 7 Inf];
>> [N,I] = sort(M)
N =
     5     2     7     4
   Inf   Inf     8     6
   Inf   Inf   Inf   Inf
I =
     2     1     3     2
     1     2     2     1
     3     3     1     3

所以这N已经是一个可能的最终产品。

中的数据Nsorted,所以如果你不想这样,你必须取消排序:

>> for ii = 1:size(M,2)        
>>     N(~isinf(N(:,ii)),ii) = M(~isinf(M(:,ii)),ii);
>> end
N =
     5     2     8     6
   Inf   Inf     7     4
   Inf   Inf   Inf   Inf

而且,如果你真的必须摆脱inf,只需发出

N(isinf(N)) = NaN;

沿线某处(和/或在需要的地方替换)isinfisnan

于 2012-11-26T07:36:17.940 回答