Vectorizing double for loop in Matlab

2019-06-07 05:01发布

问题:

I have a matrix A that contains 24 values for each day of the year (one value for each hour). Each column of A is a different day and each day has 24 rows worth of data (A is 24-by-365). I want to compare each day to each other by comparing the hour data of each day. To do this, I take one column of data and compare it to the next column. I take the difference of each hour's data in the two columns and then square and sum them to get a single value indicating how similar the two days are. I then do this with every possible combination of days, creating a 365-by-365 matrix, d, indicating how similar each day is to each other day. For example, element d(20,100) contains a value indicating how similar the 20th day of the year is to the 100th. The code is working, but it is quite slow and I would like to be able to vectorize it. Help would be greatly appreciated.

for j=1:365
    for k=1:365
        d(j,k)=sqrt(sum((A(:,j)-A(:,k)).^2));
    end
end

回答1:

Pairwise Euclidean distance using pdist, which does the heavy-lifting in C, and squareform to create the distance matrix:

d = squareform(pdist(A.'));

If you need this to be even faster (365-by-365 is not very big though), see my answer here or try this File Exchange program.



回答2:

You can't beat horchler's answer, but for completeness here's how this can be done using bsxfun

d = bsxfun(@minus, permute(A, [3 2 1]), permute(A, [2 1 3]));
d = sqrt( sum( d.^2, 3 ) );

Another nice way of doing this is using the fact that || x - y || = sqrt(||x||^2-2< x,y >+||y||^2). Therefore

n = sum(A.^2, 1); % norm of each vector
b = bsxfun(@plus, n, n') - 2 * A' * A;