Coloring labels and lines in a dendrogram plot [du

2019-09-14 21:02发布

问题:

This question is an exact duplicate of:

  • Colour the tick lables in a dendrogram to match the cluster colours 1 answer

I want to change the color of lines in the dendrogram corresponding to its label. However, I haven't seen anything like that before. So I want to at least change the color of the text labels.

回答1:

It seems like there is no simple solution for that. The labels of the dendrogram are simply the y-axis tick labels and are all sharing the same color property. On the other hand, the lines are not constructed in sets, so all the lines connecting between to adjacent nodes are one object. The following example illustrates all that:

now the question is what is your specific purpose regarding the lines to color? mainly, what would you like to do with the vertical lines?


Coloring the lables

The idea in this woraround is to replace all the lables by text, so they could be colored saparetly:

ax = gca; % get the axes handle
lab = ax.YAxis.TickLabels; % get all the labels
loc = ax.YAxis.TickValues; % get all labels location
[ulab,~,lab_ind] = unique(lab); % find all unique labels
clr = lines(numel(ulab)); % make a color map
for k = 1:numel(ulab) % for every type of lable
    ind = strcmp(ulab{k},lab); % find all instances in lab
    x = repelem(ax.XAxis.Limits(1)-0.01,sum(ind)); % make an x position vector
     % place this lable at the same locations with a distinct color:
    text(x,loc(ind),lab(ind),'Color',clr(k,:));
end
ax.YAxis.TickLabels = []; % remove the original labels
% replace the original labels with white space, to keep the axes position:
ax.YAxis.TickLabels = repelem('  ',max(cellfun(@numel,lab)));


Coloring first level lines

The idea here is similar - to place a line with the same color of the label above the current line. The nodes will be treated later.

First, we have to collect all the coordinates data from the figure:

ax = gca; % get the axes handle
X = get(ax.Children,'XData'); % Get x values of all lines
Y = get(ax.Children,'YData'); % Get y values of all lines

this has to be done before adding the colored labels (if you choose to do that too), so you won't get an error.

Then, we can loop through the lines and color them if they are placed at the y-axis ticks value (i.e. they have an integer y data). Recall (and look at the picture above for a reminder) that each line object is essentially 3 connected lines, so we want to look only at the first and last line:

for k = 1:numel(Y)
    if Y{k}(1)==fix(Y{k}(1))
        line(ax,X{k}(1:2),Y{k}(1:2),'Color',clr(lab_ind(Y{k}(1)),:),...
            'LineWidth',2);
    end
    if Y{k}(3)==fix(Y{k}(3))
        line(ax,X{k}(3:4),Y{k}(3:4),'Color',clr(lab_ind(Y{k}(3)),:),...
            'LineWidth',2);
    end
end

clr and lab_ind are taken from the code above (for the labels), and I made the line a little thicker only for clarity.

The result will be: