1

我刚刚开始探索矢量化的世界。我得到了一维矢量化,但我在矢量化以下代码时遇到了麻烦。如果可能的话,我想取消至少一个 for 循环 b/c 我计划在更大的数据集上通过多次迭代使用它,因此节省计算时间至关重要。

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 个城市,其中 3 个设有办事处。我想要一个有办公室的城市的成对矩阵来捕获每个城市之间所有单向连接的总和。上述问题的答案应该是:

 0     0     1
 2     0     0
 1     1     0

欢迎任何建议。提前致谢。

基思

4

3 回答 3

2

这是一个替代解决方案sparse

dims = max(max(CityPairs), max(Offices));
A = sparse(CityPairs(:, 1), CityPairs(:, 2), 1, dims(1), dims(2));
result = full(A(Offices, Offices));

与建议的解决方案相比,这应该会加快您的计算速度1bsxfun


1在 MATLAB 2012a 上运行速度提高 5 倍(Windows Server 2008 R2 在 2.27GHz 16 核 Intel Xeon 处理器上运行)

于 2013-10-24T08:07:13.643 回答
2

你的任务是一些选择性的交叉制表。您可以通过累积感兴趣位置的计数来轻松完成此操作,这些位置由您的索引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直接使用,但是你需要选择感兴趣的行和列:

crosstab(CityPairs(:,1),CityPairs(:,2))
ans =
     0     0     0     0     1
     2     0     1     0     0
     0     0     0     1     0
     1     0     0     0     0
     1     1     0     0     0
于 2013-10-24T08:16:22.290 回答
0

Cedric Wannaz 在 MathWorks 论坛上提供的答案

将这个设置“矢量化”并不是一件容易的事,因为有些操作需要一些查找表,并且存在累积(除非你找到技巧)。这可能会使没有 FOR 循环的方法比基于循环的基本方法更复杂(代码方面)。所以让我们先从技巧开始;-) ..

 A = double( bsxfun(@eq, CityPairs(:,1), Offices.') ) ;
 B = double( bsxfun(@eq, CityPairs(:,2), Offices.') ) ;
 A.' * B

替代方法: http: //www.mathworks.com/matlabcentral/answers/91294-vectorization-of-2-for-loops-in-matlab

于 2013-10-24T14:06:31.947 回答