MATLAB Answers

How to put a legend automatically in PCA 3D Scatter Plot?

51 views (last 30 days)
Here is my solution which successfully creates a 3D scatter plot, but I am unable to add legend to it. I will appreciate any help:
% data = mxn matrix; with all real numbers, no nan, inf or missing value.
% label = mx1 vector, e.g., label = [0;0;...;0;1;1;...;1;2;2;...;2;3;3;...;3]
myClrMap = [ 1 1 0; % Yellow
1 0 0; % Red
0 1 0; % Green
0 0 1; % Blue
[coeff_PCA, score_PCA, latent, tsquared, explained, mu] = pca(data);
h = figure();
scatter3(score_PCA(:,1), score_PCA(:,2), score_PCA(:,3), 15, label, 'filled')
class = unique(label);
% Below is my attempt to add legend which does not work.
[r, c] = size(myClrMap);
Legend = cell(r,1);
for i = 1:r
Legend{i} = strcat(length(class), num2str(i));
legend(Legend, 'location', 'best')

Sign in to comment.

Accepted Answer

Walter Roberson
Walter Roberson on 22 Sep 2021
Edited: Walter Roberson on 22 Sep 2021
scatter3(score_PCA(:,1), score_PCA(:,2), score_PCA(:,3), 15, label, 'filled')
That generates one graphical object
legend(Legend, 'location', 'best')
That can only label graphical objects. You only have one graphical object, so it can only create one legend entry.
Before telling you how to fix the problem within the code you already have:
Have you considered using one of the File Exchange gscatter3() instead ?
Walter Roberson
Walter Roberson on 23 Sep 2021
lab is a "dummy variable" name for the anonymous function
@(score_PCA,lab) scatter3(score_PCA(:,1), score_PCA(:,2), score_PCA(:,3), 15, lab, 'filled', 'displayname', NC + lab(1) )
When splitapply(FUN, score_PCA, label, G) is executed, then splitapply() will divide up the input variables score_PCA and label by rows according to the group number in the parameter G. All rows of score_PCA and label that have the same group number will be passed to the function. The selected rows of score_PCA will be passed as the first parameter, and the selected rows of label will be passed to the second parameter.
The anonymous function has to have some name to use for the (subset) of labels that was passed in, so I used the arbitary variable name lab . Because of the way we divided the groups according to label, all of the entries in lab are going to be the same, but there will be one row for each row in the selected rows from score_PCA .
I probably should also have used a different variable name for the first parameter, such as
splitapply(@(sP,lab) scatter3(sP(:,1), sP(:,2), sP(:,3), 15, lab, 'filled', 'displayname', NC + lab(1) ), score_PCA, label, G);
to emphasize that what is received as the first parameter is not the full set of score_PCA values.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!