In Matlab, I have an n^2 x n^2
matrix Corr_M
containing the Pearson correlation coefficients between all entries of a set of n x n
matrix M
, such that Corr_M(i,j)
is the correlation coefficient between M(i)
and M(j)
for some M
in the set. Note that Corr_M
is symmetric.
I would like to graph Corr_M
by showing links between different entries of M
, where the link between M(i)
and M(j)
is colored, say, red if Corr_M(i,j)
is positive and blue if it is negative. The thickness of the link indicates how strong the correlation is (preferably where links being 0.1 apart, perhaps even smaller, are distinguishable).
For a 3 x 3
M
this could look like the following:
Not all entries will be connected, as many of them are not correlated (so a correlation coefficient of zero will not result in a link being shown). Note that self-correlations are not shown. Instances such as the one seen in the bottom row, where a naive implementation might simply place one line on top of the other, are problematic, but such a naive implementation is very welcome still.
Is there a standard way of doing this, perhaps with some of the in-built graph-theoretic functions of Matlab (which I, unfortunately, do not know the scope of)?
If there isn't, then how can I implement this?
You can try the graph
object in Matlab. The following example assumes that your Corr_M
is a n
xn
matrix (see below):
% set the source of the lines:
s = repelem(1:n-1,n-1:-1:1);
% set the target of the lines:
t = nonzeros(triu(repmat(2:n,n-1,1)).').';
Corr_M(~Corr_M) = nan; % replace zero weights with nan
weights = nonzeros(tril(Corr_M,-1));
% create the graph object:
G = graph(s,t,weights,n);
% mark the lines to remove from the graph:
threshold = 0.4; % minimum correlation to plot
line_to_remove = isnan(weights) | abs(weights)<threshold;
% remove the lines from the graph:
G = G.rmedge(find(line_to_remove)); %#ok<FNDSB>
% plot it:
p = plot(G); % for labeling the lines uncomment add: 'EdgeLabel',G.Edges.Weight
p.NodeColor = 'k';
% color positive in blue and negative in red:
p.EdgeColor = [G.Edges.Weight<0.' zeros(numel(G.Edges.Weight),1) G.Edges.Weight>0.'];
% set the thickness of the lines:
p.LineWidth = abs(G.Edges.Weight)*5;
axis off
If you want the nodes to be in a grid, then you need to set the XData
and YData
properties of the plotted graph.
% get the grid coordinates for all nodes
[x,y] = ndgrid(1:ceil(sqrt(n)),1:ceil(sqrt(n)));
x = x(:);
y = y(:);
% set the nodes in a 'grid' structure
p.XData = x(1:n);
p.YData = y(1:n);
axis ij % flip the plot so it will be orderd like in a matrix
with n = 9
it will look like this (using some random Corr_M
):
Corr_M =
0 0 0 0 0 0 0 0 0
0.9504 0 0 0 0 0 0 0 0
0.016371 0.24554 0 0 0 0 0 0 0
-0.11467 -0.19375 -0.30812 0 0 0 0 0 0
-0.01241 -0.090871 0.74444 0.34121 0 0 0 0 0
-0.21623 0.36844 0.83935 -0.83914 -0.12302 0 0 0 0
-0.011428 -0.0077929 -0.26243 -0.98249 -0.57997 0.55024 0 0 0
0.64245 -0.6027 0.51424 0.62646 0.32854 0.18052 0.055688 0 0
-0.51699 0.47885 0.44677 0.18128 0.26819 -0.67849 -0.034057 0.28652 0
One of the problems with graph plots is the very small text that you can't change. If this important, read the following suggestion.