Найдите, сколько раз встречается пара значений

Предположим, что есть 2 вектора (i,j), A(10,1), B(10,1), которые получают случайные значения из [1,10] интервала. например.

A = [1 6 1 10 1 7 1 9  3 6]
B = [7 2 3  5 6 8 7 9 10 2].

Я заинтересован в создании нового вектора, который будет подсчитывать, сколько значений с одним и тем же индексом i встречается. например

 1 and 7 ⇒ 2 occurrences
 6 and 2 ⇒ 2 occurrences
 1 and 3 ⇒ 1 occurrence
10 and 5 ⇒ 1 occurrence
 1 and 6 ⇒ 1 occurrence
...

и т.п.

Таким образом, возникает окончательный массив/вектор C со всеми возможными парами и их подсчитанными экземплярами с размером C(number_of_pairs,2).


person Kots    schedule 10.02.2014    source источник
comment
@RodyOldenhuis Спасибо за уточнение!   -  person Luis Mendo    schedule 10.02.2014
comment
@LuisMendo: я думаю, что означает ОП... :)   -  person Rody Oldenhuis    schedule 10.02.2014
comment
@RodyOldenhuis Спасибо!   -  person Kots    schedule 10.02.2014


Ответы (3)


Что-то вроде этого?

C = zeros(10);

for k = 1:10
    C(A(k), B(k)) = C(A(k), B(k)) + 1
end
person Dan    schedule 10.02.2014
comment
Обратите внимание, что вы получаете то же самое с accumarray([A(:) B(:)], 1) - person Luis Mendo; 10.02.2014
comment
Разве вам не нужен C = zeros (10,10), чтобы это работало? - person Kots; 10.02.2014
comment
@Kots zeros(10) - это то же самое, что и zeros(10,10). - person Dan; 10.02.2014

Используйте accumarray, а затем find:

A = [1 6 1 10 1 7 1 9  3 6];
B = [7 2 3  5 6 8 7 9 10 2]; %// data

aa = accumarray([A(:) B(:)], 1); %// how many times each pair occurs
[ii jj vv] = find(aa);
C = [ii jj vv]; %// only pairs which occurr at least once

В вашем примере это дает

C =
     6     2     2
     1     3     1
    10     5     1
     1     6     1
     1     7     2
     7     8     1
     9     9     1
     3    10     1

Или, возможно, вам нужны aa или vv; Я не уверен, какой у вас желаемый результат.


Другой возможный подход, вдохновленный @Rody answer:

mat = [A(:) B(:)];
[bb ii jj] = unique(mat, 'rows');
C = [mat(ii,:) accumarray(jj,1)];
person Luis Mendo    schedule 10.02.2014
comment
Но имейте в виду, что пиковый объем памяти составляет O (N²) (в отличие от O (N) для зацикленного решения) - person Rody Oldenhuis; 10.02.2014
comment
@RodyOldenhuis Я добавил еще один подход, частично основанный на вашем ответе, который может использовать меньше памяти (в зависимости от того, как unique работает внутри) - person Luis Mendo; 10.02.2014
comment
Я приурочил все решения здесь. Ваше первое решение является самым быстрым как для больших, так и для малых A и B. Мое решение полное дерьмо. Решение Дэна (с включенным find) колеблется где-то посередине :) - person Rody Oldenhuis; 10.02.2014
comment
+1, но я не совсем уверен, что вам вообще нужен find. - person Dan; 10.02.2014

Что-то вроде этого?

A = [1 6 1 10 1 7 1 9  3 6];
B = [7 2 3  5 6 8 7 9 10 2];

%// Find the unique pairs
AB  = [A;B].';
ABu = unique(AB, 'rows');

%// Count the number of occurrences of each unique pair
%// (pretty sure there's a better way to do this...)     
C = arrayfun(@(ii) ...
    [ABu(ii,:) sum(all(bsxfun(@eq, AB, ABu(ii,:)),2))], 1:size(ABu,1), ...
    'UniformOutput', false);
C = cat(1,C{:});

Результат:

C =
     1     3     1
     1     6     1
     1     7     2
     3    10     1
     6     2     2
     7     8     1
     9     9     1
    10     5     1
person Rody Oldenhuis    schedule 10.02.2014
comment
@LuisMendo: Нет, наверное, обычный цикл for работает быстрее. Да ладно, твой accumarray все равно круче :) - person Rody Oldenhuis; 10.02.2014