Векторизованная функция FIND с оператором if MATLAB - PullRequest
1 голос
/ 29 мая 2019

У меня есть матрица u, я хочу просмотреть все строки и все столбцы и сделать следующее. Если элемент не равен нулю, я возвращаю значение индекса строки. Если элемент равен нулю, найдите индекс строки следующего ненулевого элемента после этого элемента. Я могу сделать это легко, используя два цикла for с функцией find. Но мне нужно делать это много-много раз (не из-за размера матрицы, а потому, что это вызывается много раз). Как я могу сделать это быстрее?

вот код цикла 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 ]

5 голосов
/ 29 мая 2019

Вы можете решить эту проблему, используя find, cummin и некоторые логические индексы .Начиная с этого примера:

>> 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 путем преобразования 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 голос
/ 30 мая 2019

@ 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...