generate a 3d scatter plot with z-support lines / pin plot / needle plot ...

I'd like to plot scattered 3d data. To enhance readability, I want to add support lines in z-direction ("needles") to the data points with matching colors, see the image below.
Is there a specific name for such a plot?
To generate the chart, I used the code below with a for loop. I wonder if you have ideas how to simplify the code.
X = rand(20, 3);
f = figure;
hsc = scatter3(X(:,1),X(:,2),X(:,3), 20, X(:,3));
cmap = colormap('cool');
axis tight
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
hold on
% draw support lines ("needles")
zlo = zlim*[1;0];
c_inter_fun = @(x) ...
interp1(linspace(zlo, zlim*[0;1], length(cmap)).' , cmap, x);
for k = 1:numel(hsc.XData)
plot3(hsc.XData(k)*[1 1], ...
hsc.YData(k)*[1 1], ...
[zlo, hsc.ZData(k)], ...
Color=c_inter_fun(hsc.ZData(k)));
end

 採用された回答

Star Strider
Star Strider 2024 年 12 月 10 日
See if the stem3 function will do what you want.
You will probably still have to use a loop of you want the individual stems and markers to be different colours, since the stem plots do not offer those options.
X = rand(20, 3);
f = figure;
hsc = stem3(X(:,1),X(:,2),X(:,3));
cmap = colormap('cool');
axis tight
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
cm = cool(size(X,1));
f = figure;
hold on
for k = 1:size(X,1)
hsc = stem3(X(k,1),X(k,2),X(k,3), 'filled', Color=cm(k,:));
end
hold off
cmap = colormap('cool');
axis tight
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
grid on
view(-27,30)
% hold on
% draw support lines ("needles")
% zlo = zlim*[1;0];
% c_inter_fun = @(x) ...
% interp1(linspace(zlo, zlim*[0;1], length(cmap)).' , cmap, x);
% for k = 1:numel(hsc.XData)
% plot3(hsc.XData(k)*[1 1], ...
% hsc.YData(k)*[1 1], ...
% [zlo, hsc.ZData(k)], ...
% Color=c_inter_fun(hsc.ZData(k)));
% end
.

10 件のコメント

Andres
Andres 2024 年 12 月 10 日
Oh my, stem/stem3 slipped my mind. I should have checked the Plot Gallery and https://www.mathworks.com/help/matlab/creating_plots/types-of-matlab-plots.html.
I just don't use it often enough. There should be cross references on the scatter3 and plot3 help page.
But thank you, this does not diminish my appreciation for the quick and helpful answers of both of you, @Star Strider and @Jacob Mathew.
Star Strider
Star Strider 2024 年 12 月 10 日
As always, my pleasure!
Andres
Andres 2024 年 12 月 10 日
And yes, unfortunately the stem3 CData property only accepts a three-element vector with a single RGB triplett, whereas its scatter3 counterpart can be an RGB array with individual colors.
Interestingly, axis tight on both plot types result in different z limits, with stem3 leaving space for a small 'stem' even for the lowest z values.
Star Strider
Star Strider 2024 年 12 月 10 日
I didn’t notice that, however I didn’t experiment with it.
I usually use
axis('padded')
.
Andres
Andres 2024 年 12 月 10 日
編集済み: Andres 2024 年 12 月 10 日
To color the stems depending on the z value: do I have to interpolate the colormap values manually?
Like this:
X = rand(20, 3);
cmap = colormap('cool');
c_inter_fun = @(x) ...
interp1(linspace(min(X(:,3)), max(X(:,3)), length(cmap)).', cmap, x);
cm = c_inter_fun(X(:,3));
figure
axis tight
hold on
for k = 1:size(X,1)
stem3(X(k,1),X(k,2),X(k,3), Color=cm(k,:));
end
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
grid on
view(-27,30)
Yes.
Your interpolation appears to be correct. I made one small change, that being to match the size of ‘cmap’ and ‘X’.
X = rand(20, 3);
cmap = cool(size(X,1));
c_inter_fun = @(x) ...
interp1(linspace(min(X(:,3)), max(X(:,3)), length(cmap)).', cmap, x);
cm = c_inter_fun(X(:,3));
figure
axis tight
hold on
for k = 1:size(X,1)
stem3(X(k,1),X(k,2),X(k,3), Color=cm(k,:));
end
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
grid on
view(-27,30)
.
.
Andres
Andres 2024 年 12 月 10 日
編集済み: Andres 2024 年 12 月 10 日
Why do you prefer
cmap = cool(size(X,1));
over
cmap = colormap('cool'); % or: cmap = cool;
You would risk loosing features of more sophisticated colormaps, e.g. compare the two color arrays c1 and c2 here:
z = [0; 0.5; 0.9; 1];
c1 = interp1(linspace(0, 1, size(z,1)).', jet(size(z,1)), z)
c2 = interp1(linspace(0, 1, size(jet,1)).', jet, z)
% c1 =
% 0 0 1.0000
% 0.5000 1.0000 0.5000
% 1.0000 0.3000 0
% 1.0000 0 0
%
% c2 =
% 0 0 0.5156
% 0.5078 1.0000 0.4922
% 0.8984 0 0
% 0.5000 0 0
Star Strider
Star Strider 2024 年 12 月 10 日
編集済み: Star Strider 2024 年 12 月 10 日
Using:
cmap = cool(size(X,1));
automatically interpolates to create individual colours for each row of ‘X’. This just makes the assignments easier.
Wiith respect to shorter colormaps, the interpolation would be the same, if you are interpolating. I characteristically limit colormaps to the number of elements in a particular vector, unless I know that I am dealing with values on a continuum or that is liikely to change.
It probably does not make any real difference, proviiding that there are enough rows in the ‘cmap’ variable to account for all the possible colours in the colormap.
EDIT — (10 Dec 2024 at 21:22)
It occurred to me later that the interpolation could be siimpliified to this by sorting X(:,3) in the interp1 call.
For that to work, ‘cmap’ has to have the same row size as ‘X’, since interp1 requires that—
X = rand(20, 3);
cmap = cool(size(X,1));
cm = interp1(sort(X(:,3)), cmap, X(:,3));
figure
axis tight
hold on
for k = 1:size(X,1)
stem3(X(k,1),X(k,2),X(k,3), Color=cm(k,:));
end
xlabel("x"), ylabel("y"), zlabel("z")
title('needle plot')
box on
grid on
view(-27,30)
.
Andres
Andres 2024 年 12 月 11 日
編集済み: Andres 2024 年 12 月 11 日
If you just want to sort the colormap values along the z-value, you don't need to interpolate.
Two sorts
[~, si] = sort(X(:,3));
[~, si] = sort(si);
cm = cmap(si,:);
or one unique
[~, ~, si] = unique(X(:,3));
cm = cmap(si,:);
would do.
As I want to link the colormap values linearly to the z-value, the explicit interpolation seems unavoidable.
Star Strider
Star Strider 2024 年 12 月 11 日
Noted.

サインインしてコメントする。

その他の回答 (1 件)

Jacob Mathew
Jacob Mathew 2024 年 12 月 10 日
Hey Andres,
You can use stem3 to achieve the effect you want. Here is an example:
X = rand(20, 3);
figure;
hold on;
% Create stem plot (needles)
stem3(X(:,1), X(:,2), X(:,3), 'Color', 'k');
% Customize plot
colormap('cool');
axis tight;
xlabel('x');
ylabel('y');
zlabel('z');
title('Needle Plot');
box on;
view(45,45); % To view the plot from a angle since plot is not interactive below
You can refer to the documentation of stem3 below:

カテゴリ

ヘルプ センター および File ExchangeGraphics Performance についてさらに検索

製品

リリース

R2024b

質問済み:

2024 年 12 月 10 日

コメント済み:

2024 年 12 月 11 日

Community Treasure Hunt

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

Start Hunting!

Translated by