Если у меня есть две матрицы A и B размером [mxn] и [pxn], и я хочу найти количество раз, которое каждая строка B появляется в A, например:
>> A = rand(5,3)
A =
0.1419 0.6557 0.7577
0.4218 0.0357 0.7431
0.9157 0.8491 0.3922
0.7922 0.9340 0.6555
0.9595 0.6787 0.1712
>> B = [A(2,:); A(1,:); A(2,:); A(3,:); A(3,:); A(4,:); A(5,:)]
B =
0.4218 0.0357 0.7431
0.1419 0.6557 0.7577
0.4218 0.0357 0.7431
0.9157 0.8491 0.3922
0.9157 0.8491 0.3922
0.7922 0.9340 0.6555
0.9595 0.6787 0.1712
с ответом в этом случае
ans =
1 2 2 1 1
, хотя, в отличие от этого примера, в общем случае m >> p
Если бы A и B были векторами, Gistc Matlab сделал бы эту работу, нокажется, что не существует эквивалента, если ячейки являются векторами.
В настоящее время я делаю это с помощью:
for i=1:length(B)
indices(i) = find(abs(A/B(i,:)-1) < 1e-15);
% division requires a tolerance due to numerical issues
end
histc(indices, 1:size(A,1))
ans =
1 2 2 1 1
, но поскольку у меня много таких матриц B, а также A и Bбольшие, это ужасно медленно.Любые идеи, как улучшить это?
РЕДАКТИРОВАТЬ:
Глядя на методы до сих пор, у меня есть следующие данные:
A 7871139x3 188907336 double
B 902x3 21648 double
Чтобы сделать вещи быстрее, я 'Я просто собираюсь использовать первые 10 строк B
B = B(1:10,:);
Обратите внимание, что для полного приложения у меня (в настоящее время) есть> 10 ^ 4 таких матриц (в конечном итоге это будет> 10 ^ 6 ....)
Мой первый метод:
tic, C = get_vector_index(A,B); toc
Elapsed time is 36.630107 seconds.
Метод bdecaf (можно уменьшить до ~ 25 секунд, удалив оператор if
и используя расстояние L1 вместо расстояния L2)
>> tic, C1 = get_vector_index(A,B); toc
Elapsed time is 28.957243 seconds.
>> isequal(C, C1)
ans =
1
метод oli's pdist2
>> tic, C2 = get_vector_index(A,B); toc
Elapsed time is 7.244965 seconds.
>> isequal(C,C2)
ans =
1
метод нормализации oli
>> tic, C3 = get_vector_index(A,B); toc
Elapsed time is 3.756682 seconds.
>> isequal(C,C3)
ans =
1
Наконец я нашел другой метод, где я ищу первый столбец, затем я ищу второйстолбец в пределах попаданий первого столбца, повторяющийся до тех пор, пока столбцы не будут исчерпаны.Пока это самый быстрый ...
N = size(A,2);
loc = zeros(size(B,1),1);
for i=1:size(B,1)
idx{1} = find(A(:,1)==B(i,1));
for k=2:N,
idx{k} = idx{k-1}(find(A(idx{k-1},k)==B(i,k)));
end
loc(i) = idx{end};
end
C = histc(loc, 1:size(A,1));
, что приводит к:
>> tic, C4 = get_vector_index(A,B); toc
Elapsed time is 1.314370 seconds.
>> isequal(C, C4)
ans =
1
Также обратите внимание, что использование intersect
намного медленнее:
>> tic, [~,IA] = intersect(A,B,'rows'); C5 = histc(IA,1:size(A,1)); toc
Elapsed time is 44.392593 seconds.
>> isequal(C,C5)
ans =
1