带if语句的矢量化FIND函数MATLAB

时间:2019-05-29 15:10:12

标签: matlab for-loop

我有一个矩阵u,我想遍历所有行和所有列并执行以下操作。如果元素不为零,则返回行索引的值。如果元素为零,则在该元素之后的下一个非零元素中查找行索引。我可以使用两个带有查找功能的for循环轻松地做到这一点。但是我需要做很多次(不是因为矩阵的大小,而是因为多次调用)。我怎样才能更快地完成?

这是for循环代码:

     for w=scenario_size:-1:1
            for t=1:time_size
                l = u(t,w) ;
                if l~=0
                    tprime = t ;
                else
                    tprime = t+ find(u(t:end,w),1,'first') -1 ;
                end
                i(t,w)       = tprime ;
                boo(t,w)     = number(tprime,w)/u(tprime,w) ;
            end
end

例如,如果一列为[0,0,5,1,0,3],则i[3,3,3,4,6,6]u的任何列的最后一个元素始终为非零(我通过在结尾处人工添加一行来强制执行此操作)。

然后,boo是某个矩阵tprime除以相应的number(在构造上非零)而对应的u条目。

2 个答案:

答案 0 :(得分:5)

您可以使用findcummin和某些logical indexing解决此问题。从此示例案例开始:

>> u = randi([0 1], 10);
>> u(end, :) = 1

u =

     0     0     0     0     1     0     1     0     1     1
     1     0     1     1     1     0     0     0     0     1
     0     0     0     0     0     1     0     1     1     0
     1     1     1     0     1     1     0     0     0     0
     0     0     1     0     0     0     0     0     1     0
     1     1     1     0     0     0     0     0     0     0
     0     1     0     1     0     0     1     1     0     1
     1     1     0     1     0     1     1     1     1     1
     1     0     0     1     0     0     1     1     1     1
     1     1     1     1     1     1     1     1     1     1

以下内容将满足您的需求:

i = nan(size(u));  % Start with all nan values
[r, ~] = find(u);  % Get row indices of non-zero values
i(u ~= 0) = r;     % Place row indices in locations of non-zero values
i = cummin(i, 1, 'reverse');  % Column-wise cumulative minimum, starting from bottom

结果:

i =

     2     4     2     2     1     3     1     3     1     1
     2     4     2     2     2     3     7     3     3     2
     4     4     4     7     4     3     7     3     3     7
     4     4     4     7     4     4     7     7     5     7
     6     6     5     7    10     8     7     7     5     7
     6     6     6     7    10     8     7     7     8     7
     8     7    10     7    10     8     7     7     8     7
     8     8    10     8    10     8     8     8     8     8
     9    10    10     9    10    10     9     9     9     9
    10    10    10    10    10    10    10    10    10    10

然后您可以通过将boo转换为linear index来计算矩阵i

index = i+time_size.*repmat(0:(scenario_size-1), time_size, 1);  % Create linear index
boo = number(index)./u(index);

或者,您可以从一开始就将i计算为线性索引:

i = nan(size(u));  % Start with all nan values
index = find(u);   % Get linear indices of non-zero values
i(index) = index;  % Place linear indices in locations of non-zero values
i = cummin(i, 1, 'reverse');  % Column-wise cumulative minimum, starting from bottom
boo = number(i)./u(i);

答案 1 :(得分:1)

@gnovice 答案很好,只是为find函数提供了一个替代方法

  • 首先使用u矩阵
    >> u = randi([0 1], 10);
    u(end, :) = 1;
    >> u

    u =

         0     0     0     0     0     1     1     0     0     0
         0     1     1     1     0     1     0     1     1     1
         1     1     1     0     1     0     0     1     1     0
         1     1     1     1     1     0     1     1     0     1
         1     1     0     1     1     1     1     0     0     0
         0     0     1     0     1     1     1     0     0     1
         0     1     0     0     1     1     0     0     0     1
         0     1     0     1     1     1     0     1     1     0
         0     0     0     1     0     1     1     1     1     1
         1     1     1     1     1     1     1     1     1     1
  • 然后可以按如下方式计算non-zeros行索引
    >> t = 1:10*10;% All elements indices
    r = t(u ~= 0); % All non-zeros elements indices 
    >> r

    r =

      Columns 1 through 18

         3     4     5    10    12    13    14    15    17    18    20    22    23    24    26    30    32    34

      Columns 19 through 36

        35    38    39    40    43    44    45    46    47    48    50    51    52    55    56    57    58    59

      Columns 37 through 54

        60    61    64    65    66    69    70    72    73    74    78    79    80    82    83    88    89    90

      Columns 55 through 60

        92    94    96    97    99   100