Reputation: 719
I have a 19 x 39 double M containing data for 19 network nodes in 39 different network configurations. Each column (i.e., each configuration) shows how which of these nodes group together into a network. If they belong to the same network, they will have the same value. The value also indicates how many networks there are. For instance, M could look like this:
1 1 1
1 2 2
3 2 1
1 2 2
2 3 2
2 3 3
2 3 3
1 3 3
1 2 2
2 1 2
1 1 3
1 1 1
2 2 1
1 2 2
2 2 2
2 2 3
3 1 3
2 1 1
2 3 1
This means that for column 1 (or configuration 1) there are three networks in this one configuration: network 1 containing nodes 1, 2, 4, 8, 9, 11, 12, 14; network 2 containing nodes 5, 6, 7, 10, 13, 15, 16, 18, 19; network 3 containing nodes 3, 17. Now, I want to calculate across 39 configurations (or columns) the number of the times each node belongs to the same network with each remaining node. In this example, node 1 belong to the same network with node 2 once while node 4 and 9 belong to the same network 3 times. I imagine the output would be a 19 x 19 matrix with each cell indicating how many times the node from the y axis is in the same network with the node in the x axis. The diagonal line is then 39 (as each node belong to the same network with itself for each configuration). Does anyone have a suggestion how to do this efficiently?
Upvotes: 3
Views: 66
Reputation: 65430
You should be able to use bsxfun
to check the equality of the matrix a
with a permuted version of a
. You can then sum
across the second dimension to give you the number of co-occurances of two nodes in a given network and squeeze the result to get a 2D matrix
squeeze(sum(bsxfun(@eq, a, permute(a, [3 2 1])), 2))
The row/column of a given element in the output correspond to the number of times that the two nodes were in the same group.
As a simple example
a = [1 1 1
1 2 1;
2 2 1];
b = squeeze(sum(bsxfun(@eq, a, permute(a, [3 2 1])), 2))
% 3 2 1
% 2 3 2
% 1 2 3
From this, nodes 1 and 2, b(1,2)
, appeared in the same group 2 times (networks 1 and 3). Nodes 1 and 3, b(1,3)
appeared in the same network once (network 3). Nodes 2 and 3, b(2,3)
, appeared in the same network twice (networks 2 and 3).
If you are using MATLAB R2016b or newer this can be simplified to
squeeze(sum(a == permute(a, [3 2 1]), 2));
Rather than considering the entire matrix of networks, let's first consider just the first network. We want to compare the group assigned to each node with the group assigned to every other node. We can create that matrix using bsxfun
tmp = bsxfun(@eq, a(:,1), a(:,1).')
% 1 1 0
% 1 1 0
% 0 0 1
Now if we did this for each network (column) of a
we would get N
of these matrix.
% Create a 3D matrix to hold co-occurance data
counts = zeros(size(a, 1), size(a, 1), size(a, 2));
for k = 1:size(a, 2)
counts(:,:,k) = bsxfun(@eq, a(:,k), a(:,k).');
end
% Now count how many times two nodes were placed in the same group
nSameGroup = sum(counts, 3);
While this loop works, we can instead reshape the third input to bsxfun
a little bit (using permute
) such that it will create the counts
matrix automatically.
tmp = bsxfun(@eq, a, permute(a, [3 2 1]))
% tmp(:,:,1) =
% 1 1 1
% 1 0 1
% 0 0 1
% tmp(:,:,2) =
% 1 0 1
% 1 1 1
% 0 1 1
% tmp(:,:,3) =
% 0 0 1
% 0 1 1
% 1 1 1
And then we sum along the second dimension to compute the number of co-occurrences and squeeze the result to get a 2D matrix.
squeeze(sum(tmp, 2))
% 3 2 1
% 2 3 2
% 1 2 3
Upvotes: 3