Я только начал изучать мир векторизации. Я получил одномерную векторизацию, но у меня возникли проблемы с векторизацией следующего кода. Я хочу покончить, по крайней мере, с одним из циклов for, если это возможно, потому что я планирую использовать это на гораздо большем наборе данных во многих итерациях, поэтому экономия времени вычислений имеет существенное значение.
CityPairs = [7 3
3 1
3 1
1 7
7 1
3 4
5 1
4 6];
Offices = [1;3;7];
nOffices = size(Offices,1);
connection = zeros(nOffices);
for i = 1:nOffices
for j = 1:nOffices
connection(i,j) = sum(Offices(i) == CityPairs(:,1)...
& CityPairs(:,2) == Offices(j));
end
end
disp(connection)
В этом примере 7 городов, в трех из которых есть офисы. Я хочу, чтобы попарная матрица для городов с офисами отражала сумму всех односторонних соединений между ними. Ответ на вышеуказанную проблему должен быть:
0 0 1
2 0 0
1 1 0
Любые предложения приветствуются. Заранее спасибо.
Кейт
Есть ли причина для connection(i,:) = connection(i,:);? В противном случае удалите строку. Daniel 24.10.2013
это было частью чего-то другого, что я сделал, здесь это неважно - я удалил это. Keith D 24.10.2013
Итак, вы хотите еще один ответ или ваша проблема решена? chappjc 24.10.2013
проблема решена. я просто не мог опубликовать свой ответ, пока не прошло 6 часов. спасибо за альтернативные решения - я проверю их позже и отдам должное тем, которые работают должным образом. Keith D 24.10.2013
dims = max(max(CityPairs), max(Offices));
A = sparse(CityPairs(:, 1), CityPairs(:, 2), 1, dims(1), dims(2));
result = full(A(Offices, Offices));
Это должно немного ускорить ваши вычисления1 по сравнению с предлагаемым bsxfun решением.
1 Работает в 5 раз быстрее на MATLAB 2012a (Windows Server 2008 R2 на 16-ядерном процессоре Intel Xeon с частотой 2,27 ГГц)
Ответ 2 · рейтинг 2 · Oleg
Ваша задача - некоторая выборочная перекрестная таблица. Вы можете легко добиться этого, накапливая счетчики для интересующих позиций, проиндексированных вашим Offices:
% Row and col subs
[~,rsubs] = ismember(CityPairs(:,1),Offices);
[~,csubs] = ismember(CityPairs(:,2),Offices);
% Select where both belong to Offices, i.e. non 0
subs = [rsubs,csubs];
subs = subs(all(subs,2),:);
% Accumulate
accumarray(subs,1)
Результат
ans =
0 0 1
2 0 0
1 1 0
Если у вас есть панель инструментов статистики, вы можете использовать crosstab напрямую, но тогда вам нужно будет выбрать интересующие строки и столбцы:
Ответ предоставлен Седриком Ванназом на форуме MathWorks.
Нетривиально "векторизировать" эту настройку, так как есть операции, требующие некоторой таблицы поиска, и есть накопление (если вы не найдете хитрости). Это, вероятно, сделает подход без циклов FOR более сложным (с точки зрения кода), чем базовый подход, основанный на циклах. Итак, давайте начнем сначала с трюка ;-) ..
A = double( bsxfun(@eq, CityPairs(:,1), Offices.') ) ;
B = double( bsxfun(@eq, CityPairs(:,2), Offices.') ) ;
A.' * B