问题
How can I individually colour the labels of a dendrogram so that they match the colours of the clusters in MATLAB?
Here is an example desired output generated using the code in my answer below (note the lables are just the 50 charater series 'A':'r'
):
If there is a more straightforward way to do this, please do post an answer as I was unable to find the solution to this by googling. If not, the code is below for posterity.
回答1:
I could not find a definitive answer to this but I managed to piece the following together from a couple of ideas (shown in the comments) I found online. Hopefully this is useful to someone.
I'm assuming that your data you are clustering is in the matrix data
and that labels
are stored in a cell array called labels:
%% Hierarchical clustering
T = linkage(data,'average','spearman');
D = pdist(data, 'spearman');
leafOrder = optimalleaforder(T, D);
th = 0.726;
H = dendrogram(T, 0,'ReOrder', leafOrder, 'Orientation', 'left', 'ColorThreshold', th);
h = gca;
set(h, 'YTickLabel', labels(leafOrder));
%Changing the colours
%First get a list of the colours of each line object
lineColours = cell2mat(get(H,'Color'));
colourList = unique(lineColours, 'rows');
% For each cluster (i.e. for each unique colour)
for colour = 1:size(colourList,1)
% see http://stackoverflow.com/a/16677119/1011724 for the idea of
% copying the axis
ax = copyobj(gca, gcf);
% see http://undocumentedmatlab.com/blog/customizing-axes-rulers for
% more on YRuler. This might not work on older versions of MATLAB.
yruler = ax.YRuler;
rgb = floor(colourList(colour,:)'*255);
% Make all the datalabels of the new axis the current colour. (We will
% later make those labels that aren't this colour empty.)
yruler.TickLabels.ColorData = uint8([rgb;255]);
% Might not be necessary, but stopped me getting errors
pause(0.1)
% The hard bit is figuring out which line object matches which label
% Note that there might be an easier way if you are willing to alter your dendrogram.m file: http://www.mathworks.com/matlabcentral/newsreader/view_thread/134997
idx = ismember(lineColours, colourList(colour,:), 'rows');
clusterNodes = [T(idx,1);T(idx,2)];
% Cluster nodes greater than the number of data points are none terminal
% nodes and thus not of interest.
[~,c]=find(bsxfun(@eq,clusterNodes(clusterNodes < length(labels)+1),leafOrder))
% Convert to a logical index
idx = ~ismember(1:(size(lineColours,1)+1), c);
n = sum(idx);
% Set the labels we don't want to colour (this iteration) to be empty
% char arrays.
yruler.TickLabels.String(idx) = mat2cell(repmat(char(),n,1),zeros(n,1),0);
end
来源:https://stackoverflow.com/questions/34947840/colour-the-tick-lables-in-a-dendrogram-to-match-the-cluster-colours