为树状图中的刻度标签着色以匹配簇颜色

Colour the tick lables in a dendrogram to match the cluster colours

如何单独为树状图的标签着色,使其与 MATLAB 中簇的颜色相匹配?

这是使用下面我的答案中的代码生成的所需输出示例(注意标签只是 50 个字符的系列 'A':'r'):

如果有更直接的方法,请 post 回答,因为我无法通过谷歌搜索找到解决方案。如果没有,代码如下 posterity.

我找不到明确的答案,但我设法从我在网上找到的几个想法(显示在评论中)中拼凑出以下内容。希望这对某人有用。

我假设您要聚类的数据在矩阵 data 中并且 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  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