Найти индексы строк различных значений в матрице

Имея матрицу A (n*2) в качестве источника и B в качестве вектора, содержащего подмножество элементов A, я бы хотел найти индекс строки элементов.

A=[1 2;1 3; 4 5];
B=[1 5];
F=arrayfun(@(x)(find(B(x)==A)),1:numel(B),'UniformOutput',false)

дает следующие выходные данные в ячейке согласно этой странице справки

[2x1 double]    [6]

с указанием индексов всех встречаемости по столбцам. Но я бы хотел иметь индексы строк. т.е. я хотел бы знать, что элемент 1 находится в строке 1 и строке 2, а элемент 5 - только в строке 3. Если бы индексы были построчными, я мог бы использовать ceil(F{x}/2), чтобы получить желаемый результат, Теперь с переменным количеством строк, каково ваше предлагаемое решение? Может случиться так, что в функции ismember нет полного тега включения 'rows'. Кроме того, я хотел бы знать все показатели указанных элементов. Заранее благодарю за любую помощь.

3 ответа

Решение

Подход 1

Преобразовать F из текущей формы линейного индекса в индексы строк используйте mod:

rows = cellfun(@(x) mod(x-1,size(A,1))+1, F, 'UniformOutput', false);

Вы можете объединить это с вашим кодом в одну строку. Обратите внимание, что вы можете напрямую использовать B в качестве входа в arrayfun и вы избегаете одного этапа индексации:

rows = arrayfun(@(x) mod(find(x==A)-1,size(A,1))+1, B(:), 'UniformOutput', false);

Как это работает:

F как дано вашим кодом является линейным индексом в форме столбца. Это означает, что индекс работает по первому столбцу B, начало начинается в верхней части второго столбца и снова уменьшается, и т. д. Таким образом, номер строки можно получить только по модулю (mod) операция.

Подход 2

С помощью bsxfun а также accumarray:

t = any(bsxfun(@eq, B(:), reshape(A, 1, size(A,1), size(A,2))), 3); %// occurrence pattern
[ii, jj] = find(t); %// ii indicates an element of B, and jj is row of A where it occurs
rows = accumarray(ii, jj, [], @(x) {x}); %// group results according to ii

Как это работает:

Если предположить, A а также B как в вашем примере, t это матрица 2x3

t =
     1     1     0
     0     0     1

М-й ряд t содержит 1 в столбце n, если m-й элемент B происходит в n-м ряду B, Эти значения преобразуются в форму строки и столбца с find:

ii =
     1
     1
     2
jj =
     1
     2
     3

Это означает, что первый элемент B в рядах 1 и 2 A; а второй происходит в строке 3 B,

Наконец, значения jj сгруппированы (с accumarray в соответствии с их соответствующей стоимостью ii генерировать желаемый результат.

Один подход с bsxfun & accumarray -

%// Create a match of B's in A's with each column of matches representing the
%// rows in A where there is at least one match for each element in B 
matches = squeeze(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))

%// Get the indices values and the corresponding IDs of B
[indices,B_id] = find(matches)
%// Or directly for performance:
%// [indices,B_id] = find(any(bsxfun(@eq,A,permute(B(:),[3 2 1])),2))

%// Accumulate the indices values using B_id as subscripts
out = accumarray(B_id(:),indices(:),[],@(x) {x})

Пробный прогон -

>> A
A =
     1     2
     1     3
     4     5
>> B
B =
     1     5
>> celldisp(out) %// To display the output, out
out{1} =
     1
     2
out{2} =
     3

С arrayfun, ismember а также find

[r,c] = arrayfun(@(x) find(ismember(A,x)) , B, 'uni',0);

куда r дает желаемые результаты, вы также можете использовать c переменная, чтобы получить столбец каждого числа в B

Результаты для ввода образца:

>> celldisp(r)

r{1} =
 1
 2

r{2} = 
 3


>> celldisp(c)

c{1} = 
 1
 1

c{2} =
 2
Другие вопросы по тегам