Поиск того, попадают ли строки матрицы в Matlab в строки другой матрицы - PullRequest
0 голосов
/ 31 августа 2018

У меня есть матрица Ksets в Matlab с размером Gx(l*N) и матрица A с размером MxN.

Каждая строка Ksets может быть разбита на l подстрок размером 1xN.

Позвольте мне объяснить лучше на примере.

clear
N=3;
l=4;
G=2;
M=5;

Ksets=[1 2 3      5 6 7      9 10 11   0 0 0;
       13 14 15   1 2 3      21 22 23  1 1 1]; %Gx(l*N)

A=[1 2 3; 
   5 6 7; 
   21 22 23; 
   1 2 3;
   0 0 0]; %MxN

В примере:

  • строка 1 из Ksets состоит из l подстрочек размером 1xN: [1 2 3], [5 6 7], [9 10 11], [0 0 0];

  • строка 2 из Ksets состоит из l подстрочек размером 1xN: [13 14 15], [1 2 3], [21 22 23], [1 1 1].

Я предполагаю, что каждая строка Ksets не содержит равных подстрок.

Я хотел бы, чтобы вы помогли построить матрицу Response с размером GxM с Response(g,m)=1, если строка A(m,:) равна одной из l подстрок Ksets(g,:) и нулю в противном случае.

Продолжая пример выше

Response= [1 1 0 1 1; 
           1 0 1 1 0]; %GxM

Этот код делает то, что я хочу:

Responsecorrectmy=zeros(G, M);
for x=1:G
    for c=1:l
        Responsecorrectmy(x,:)=Responsecorrectmy(x,:)+...
                               ismember(A,Ksets(x,(c-1)*N+1:c*N), 'rows').';
    end
end

Мой код состоит из 2 циклов, что нежелательно, потому что в моем реальном алгоритме G,l большие. У вас есть предложения без петель?

Ответы [ 2 ]

0 голосов
/ 01 сентября 2018

Это можно сделать с небольшим изменением формы и изменением размеров:

Response = permute(any(all(bsxfun(@eq, reshape(Ksets.', N, [], G), permute(A, [2 3 4 1])), 1), 2), [3 4 1 2]);

Это работает следующим образом:

  1. reshape(Ksets.', N, [], G) преобразует Ksets в 3D-массив N × l × G, так что теперь каждая подстрока отделяется от других.
  2. bsxfun(@eq, ..., permute(A, [2 3 4 1])) создает N × l × G × M 4D-массив с результатом сравнения каждого элемента 3D-массива из шага 1 с каждым значением в A.
  3. all(..., 1) проверяет, совпадают ли все элементы каждой подстроки (то есть первое измерение). any(...,2) проверяет, происходит ли это для любой подстроки одной из исходных строк (т.е. второго измерения).
  4. permute(..., [3 4 1 2]) удаляет первые два измерения (которые стали единичными на шаге 3), давая желаемый результат G × M. (Было бы небезопасно использовать squeeze для этого, потому что это неправильно удалит третье измерение, если G=1).
0 голосов
/ 31 августа 2018

Это довольно сложно сделать векторизованным, особенно если подмножества, с которыми вы пытаетесь сравнивать, встроены в каждую строку. Что может быть сделано для повышения эффективности, так это изменить Ksets в трехмерную матрицу, где каждый срез содержит те подмножества, отформатированные в 2D матрицу, где каждое подмножество основано на каждой строке. Затем вы можете использовать ismember в сочетании с использованием только одного цикла в каждой строке отдельно и заполнить результаты.

Ksets2 = permute(reshape(Ksets.', [N l G]), [2 1 3]);
Response = false(G, M);
for i = 1 : G
    Response(i, :) = ismember(A, Ksets2(:,:,i), 'rows')';
end

Первый оператор изменяет ваши данные таким образом, что он становится трехмерной матрицей, но из-за основной обработки столбца в MATLAB и из-за того, что ваши подмножества располагаются в основной строке, мы должны транспонировать данные до изменения формы. Однако это приводит к тому, что каждый столбец находится в подмножестве, поэтому мы должны транспонировать каждый фрагмент независимо с помощью операции permute.

Как только это будет сделано, мы выделяем матрицу нужного размера, а затем перебираем каждую строку в Ksets (теперь преобразована в строки подмножеств), чтобы получить желаемый результат.

Получаем:

>> Response

Response =

  2×5 logical array

   1   1   0   1   1
   1   0   1   1   0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...