Spider Plot with Standard Deviation as shaded region

I want to plot a spider plot where each spoke represents the average value with solid line. In addition, I want to show standard deviation as shaded region around the average plot (Average+SD and Average-SD). I have attached a figure to show the desired outcome.
Thank you in advance.

2 Comments

you can probably add the shaded area in this existing code :
Yes, I am using this code only. But, if I am keeping 'fill' as 'on' it is filling the etire region starting from the origin. I only want to have SD region as shaded one.
Thank you for the response.

Sign in to comment.

 Accepted Answer

hello again
I just created a quick and dirty slightly modified function (sorry for messing it ! ) , so I could suggest this - if this is what you want
for the demo I assumed that each D vector has a correspond std vector called stdD which here is 10% of its nominal D value (of course you can put your own data in here)
custom function is attached (my apologizes to it's creator !) (NB : I simply deactivated certain checks which would otherwise throw error messages)
my result :
% Initialize data points
D1 = [5 3 9 1 2];
D2 = [5 8 7 2 9];
D3 = [8 2 1 4 6];
P = [D1; D2; D3];
% Multiple shaded regions
stdD1 = 0.1*D1;
stdD2 = 0.1*D2;
stdD3 = 0.1*D3;
axes_shaded_limits = {...
[D1-stdD1;D1+stdD1],... % [min axes limits; max axes limits]
[D2-stdD2;D2+stdD2],...
[D3-stdD3;D3+stdD3]};
% Spider plot
spider_plot_mod1(P,...
'AxesShaded', 'on',...
'AxesShadedLimits', axes_shaded_limits,...
'AxesShadedColor', {'b', 'r','y'},...
'AxesShadedTransparency', 0.1);

8 Comments

Hello,
While implementing this code on my data, I am receiving the following warnings and then a figure is getting plotted which doesn't contain data points:
Warning: Output contains an empty polyshape due to duplicate vertices, intersections, or other
inconsistencies.
Warning: Polyshape has duplicate vertices, intersections, or other inconsistencies that may produce
inaccurate or unexpected results. Input data has been modified to create a well-defined polyshape.
I am not able to figure out the reason for it.
I will be grateful if you can kindly look into the issue. I am enclosing the code, figure and the data.
Thank you so much.
ok I understand - as I learn how to use the function spider_plot
To avoid this situation you have to use the argument AxesLimits
here for example the same code I used above in my first answer, but with now the axis limits argument
NB it's a different argument , not to confuse with AxesShadedLimits
see the plot has now all axes in range 0 to 10 as specified by argument AxesLimits
% Initialize data points
D1 = [5 3 9 1 2];
D2 = [5 8 7 2 9];
D3 = [8 2 1 4 6];
P = [D1; D2; D3];
% Multiple shaded regions
stdD1 = 0.1*D1;
stdD2 = 0.1*D2;
stdD3 = 0.1*D3;
% shaded area limits
axes_shaded_limits = {...
[D1-stdD1;D1+stdD1],... % [min axes limits; max axes limits]
[D2-stdD2;D2+stdD2],...
[D3-stdD3;D3+stdD3]};
% axes limits
AxesLimits_min = zeros(1,size(P,2));
AxesLimits_max = ceil(max(P(:))+1)*ones(1,size(P,2));
AxesLimits = [AxesLimits_min; AxesLimits_max];
% Spider plot
spider_plot_mod1(P,...
'AxesShaded', 'on',...
'AxesLimits',AxesLimits,...
'AxesShadedLimits', axes_shaded_limits,...
'AxesShadedColor', {'b', 'r','y'},...
'AxesShadedTransparency', 0.3);
now if I transpose with your data / code , this would be :
load('NormalizedVoluntaryAverageFeaturesWithSD.mat');
Average=AverageVoluntaryAverageNMR(:,:,:,1);
SD = SDVoluntaryAverageNMR(:,:,:,1);
UpperBound = Average+SD;
LowererBound = Average-SD;
% shaded area limits
axes_shaded_limits = {[LowererBound;UpperBound]};
% axes limits
AxesLimits_min = floor(min(Average(:)))*ones(1,size(Average,2));
AxesLimits_max = ceil(max(Average(:)))*ones(1,size(Average,2));
AxesLimits = [AxesLimits_min; AxesLimits_max];
% Spider plot
spider_plot_mod1(Average,...
'AxesShaded', 'on',...
'AxesLimits',AxesLimits,...
'AxesShadedLimits', axes_shaded_limits,...
'AxesShadedColor', {'b'},...
'AxesShadedTransparency', 0.3);
if you want to "zoom" the axes range , you can change the definition of AxesLimits
like here :
load('NormalizedVoluntaryAverageFeaturesWithSD.mat');
Average=AverageVoluntaryAverageNMR(:,:,:,1);
SD = SDVoluntaryAverageNMR(:,:,:,1);
UpperBound = Average+SD;
LowererBound = Average-SD;
% shaded area limits
axes_shaded_limits = {[LowererBound;UpperBound]};
% axes limits
% AxesLimits_min = floor(min(Average(:)))*ones(1,size(Average,2));
% AxesLimits_max = ceil(max(Average(:)))*ones(1,size(Average,2));
AxesLimits_min = (min(Average(:))-0.1)*ones(1,size(Average,2));
AxesLimits_max = (max(Average(:))+0.1)*ones(1,size(Average,2));
AxesLimits = [AxesLimits_min; AxesLimits_max];
% Spider plot
spider_plot_mod1(Average,...
'AxesShaded', 'on',...
'AxesLimits',AxesLimits,...
'AxesShadedLimits', axes_shaded_limits,...
'AxesShadedColor', {'b'},...
'AxesShadedTransparency', 0.3);
Thank you so much. It is perfectly fine now.
hello
there is a small change in the code that is not evident to see , but it makes a difference in term of size() and that is the reason why it didn't work in first place
the correct way to generate the axes_shaded_limits :
axes_shaded_limits = {[LowerBoundUp;LowerBoundDown],...
[UpperBoundUp;UpperBoundDown]}; % shaded area limits
and this has size : axes_shaded_limits = 1×2 cell array, {2×8 double} {2×8 double}
the way you coded is not equivalent :
UpperBound = [UpperBoundUp;UpperBoundDown];
LowerBound = [LowerBoundUp;LowerBoundDown];
axes_shaded_limits = {[LowerBound,...
UpperBound]};
will generate this output : axes_shaded_limits = 1×1 cell array, {2×16 double}
which is incorrect (in size) and will generate the error msg
Updated code is attached
all the best
Yes, I got stuck there but got that resolved.
just a little change: according to my problem, the axes_shaded_limit would be
axes_shaded_limits = {[LowerBoundUp;UpperBoundUp],...
[LowerBoundDown;UpperBoundDown]};
as the average will have shaded region of lower and upper bounds (for Up and Down condition which corresponds to spider plots on a single tile, in my case).
Just wanted to clarify, if anyone wants to use the same in future.
I sincerely appreciate your help. Thank you so much.

Sign in to comment.

More Answers (1)

You can do it like this:
I am not aware of a function, so you have to do it on your own.
Note that this functions uses values maxval = 7 and offset = 4 that are tailored to your data to have an axis running from -4 to 3.
Your friend is pol2cart to convert all the polar stuff to Cartesian coordinates and then use plot, patch or line commands.
function spiderplot(val, sd, col)
if nargin < 1
val = [-1 -1 1 -1 -1 -1 0];
end
if nargin < 2
Nspokes = size(val, 2);
sd = ones(1, Nspokes) + 0.5*rand(1, Nspokes);
end
if nargin < 3
col = 'r'; % or [234 170 58]/266; or 'g' or any other color
end
labels = {'Degree', 'Density', 'Betweeness Centrality', 'Closeness', 'Eigenvector', 'Transivity', 'Entropy'};
offset = 4; % map the smallest value to 0
maxval = 7;
val = val + offset;
Nspokes = size(val, 2);
theta = linspace(0, 2*pi, Nspokes + 1);
%% plot the axes (background, circles and spokes)
% add a grayish background circle
col_bg = [229, 236, 246]/255;
Npoints = 100;
thetaN = linspace(0, 2*pi, Npoints);
[xc, yc] = pol2cart(thetaN, maxval);
patch(xc, yc, col_bg, 'EdgeColor', 'none')
hold on
% add the spokes
for i = 1:Nspokes
[xs, ys] = pol2cart(theta(i), maxval);
line([0, xs], [0, ys], 'Color', 'w')
end
% add the circles
for i = 1:maxval
[xc, yc] = pol2cart(thetaN, i);
plot(xc, yc, 'w-')
end
% label the axis
for i = 0:maxval
str = int2str(i - offset);
% change dash to minus:
str = strrep(str, '-', char(hex2dec('2212')));
text(i, 0, str, 'FontSize', 14,...
'HorizontalAlignment', 'center', 'VerticalAlignment', 'top')
end
axis off
%% plot the data
% append first element to plot a closed curve
val = [val, val(:, 1)];
sd = [sd, sd(:, 1)];
% plot data
[x, y] = pol2cart(theta, val); % convert to Cartesian
plot(x, y, '-', 'Color', col)
hold on
% plot sd lines
[x1, y1] = pol2cart(theta, val - sd);
[x2, y2] = pol2cart(theta, val + sd);
plot(x1, y1, '--', 'Color', col)
plot(x2, y2, '--', 'Color', col)
% shade the area between the +/- SD lines
h = patch([x1 fliplr(x2)], [y1 fliplr(y2)], col,...
'EdgeColor', 'none', 'FaceAlpha', 0.2);

1 Comment

Thank you so much for considering even the minor details of the example figure.

Sign in to comment.

Products

Release

R2023b

Community Treasure Hunt

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

Start Hunting!