Austin
Austin

Reputation: 8585

Series color in scatter3 does not match Legend when using for-loop MATLAB

Problem:

The legend colors in my scatter3 plot do not match the series colors after using a for loop.

Background:

I'm writing a script to produce a 3d plot based on experimental data. I process the data in R, as well. So the data is formatted as a data.frame (i.e. a nx7 CSV with headers are Value Gain Cost, Entropy, Risk, Credibility, algorithm, color, pch). I want the resulting 3d scatter plot to add a point for each observation (i.e. each [x,y,z] element) and color it according to its pch value (e.g. all observations with pch==1 should be the same color).

Code:

%get & count unique pch values ommitting NANs
UniquePchVal =transpose(unique(pch));
numberOfUniquePchVals=length(UniquePchVal(~isnan(UniquePchVal)))
UniquePchVal = UniquePchVal(1:numberOfUniquePchVals);

% get boolean vector for each series to indicate which observations should
% are to be included
numberOfObservations=length(pch)
UniquePchValMatrix = repmat(UniquePchVal,numberOfObservations,1);
pchMatrix=repmat(pch,1,numberOfUniquePchVals);
rows=UniquePchValMatrix(1:numberOfObservations,1:numberOfUniquePchVals);
rows =(rows==pchMatrix);

%make the plot
hold on
for i=1:numberOfUniquePchVals
   x=ValueGain(rows(:,i));
   y=Cost(rows(:,i));
   z=Risk(rows(:,i));
   size=repmat(20,length(x),1);
   color=repmat(i,length(x),1);
   h(i)=scatter3(x,y,z,size,color,'filled');
end
xlabel('Value Gain')
ylabel('Cost')
zlabel('Risk')
legend(h,unique(algorithm))
hold off

Result:

Executing the code produces a legend where each dot is the same color. Result from executing the above code

Sample Data:

Value Gain  Cost    Entropy Risk    Credibility algorithm   color   pch
-0.0    0.0 -0.0    0.0 -0.0    MOEAD   orange  3
-1.39838    1.44    -1.0    2.55555 -1.0    MOEAD   orange  3
-1.41319    4.15    -1.0    1.55555 -1.0    MOEAD   orange  3
-1.39593    3.84    -1.0    1.55555 -1.0    MOEAD   orange  3
-1.25189    1.11    -0.5    1.55555 -1.0    IBEA    cornflowerblue  4
-1.43183    2.87    -0.5    2.55555 -1.0    IBEA    cornflowerblue  4
-1.38953    1.43    -1.0    1.55555 -1.0    NSGA2   #fb8072 5
-1.39585    1.13    -0.33333    1.55555 -1.0    NSGA2   #fb8072 5
-1.1792 1.0 -0.2    2.55555 -1.0    NSGA2   #fb8072 5
-1.38244    1.14    -1.0    1.55555 -1.0    NSGA2   #fb8072 5
-0.05665    0.89    -1.0    2.55543 -1.0    NSGA2   #fb8072 5
-0.1175 0.9 -0.5    1.55556 -1.0    NSGA2   #fb8072 5
-0.06518    0.75    -0.33333    1.55555 -1.0    NSGA2   #fb8072 5
-0.51192    0.98    -0.5    1.55555 -1.0    NSGA2   #fb8072 5
-0.77432    0.98    -1.0    2.55555 -1.0    NSGA2   #fb8072 5
-0.82269    0.94    -0.25   2.55555 -1.0    NSGA2   #fb8072 5
-0.92626    1.0 -1.0    1.55555 -1.0    NSGA2   #fb8072 5

Upvotes: 4

Views: 424

Answers (1)

Thijs D
Thijs D

Reputation: 782

If all markers are the same colour, or there are only a few distinct colours, it is much more efficient to just use line instead of scatter3; the latter makes one handle per marker, line has one handle for all points. scatter3 with many points can bring Matlab to a halt.

Added bonus when using line is that the legend works as expected:

colors = ['r','g','b'];
hold on
h = [];
for ii = 1:3
    x = rand(10,1);
    y = rand(10,1);
    z = rand(10,1);
    h(ii) = line(x,y,z);
    set(h(ii),...
        'Marker','.',...
        'MarkerEdgeColor',colors(ii),...
        'MarkerFaceColor',colors(ii),...
        'MarkerSize',10,...
        'LineStyle','none')
end
legend('a','b','c')

Upvotes: 1

Related Questions