Stem plot inside a for loop
4 次查看(过去 30 天)
显示 更早的评论
Hi,
I have a structure (attached) with the data arranged as follows:
for k=1:n
structure.stormk.data
where data refers to 10 different doubles.
I need a stem plot with the format attached (picture). The x-axis will cover k=1:n storms, and the data is plotted for each of them as shown.
At the end I will end up with 10 of these plots (data), covering the k storms.
Can I get some help with this type of plot? Thanks
![example_plot.png](https://www.mathworks.com/matlabcentral/answers/uploaded_files/201487/image.png)
0 个评论
采纳的回答
Guillaume
2019-1-25
Numbered variables, fields, etc. are almost always a bad idea. You end up writing meta-code to manipulate the variable, field, whatever names instead of writing code to manipulate the content of the variables. In your particular case, since the lexicographical order of your field names does not correspond to the numerical order, you're going to have to first use a special sort on your field names (I assume you want storm2 to be plotted before storm11). There's a simple way to have numbers associated with things in matlab, the indices of arrays.
So, instead of
LTA_stormplot_motions.storm1
LTA_stormplot_motions.storm2
LTA_stormplot_motions.storm3
you should have one storm field which is a structure array:
LTA_stormplot_motions.storm(1)
LTA_stormplot_motions.storm(2)
LTA_stormplot_motions.storm(3)
Or even simpler, since the structure would have only one field:
LTA_stormplot_motions(1)
LTA_stormplot_motions(2)
LTA_stormplot_motions
You should modify whatever code you used to create that structure to get the latter. If it's really not possible we can convert the former. You'll need a special sort function such as natsort by Stephen Colbeldick:
[~, order] = natsort(fieldnames(LTA_stormplot_motions)); %requires natsort from the fileexchange
LTA_stormplot_motions = orderfields(LTA_stormplot_motions, order);
LTA_stormplot_motions = structfun(@(f) f, LTA_stormplot_motions);
Note that I've ignored that storm 38 is missing from your structure. The above will renumber storm 39-77 to 38-76. If that's not desired, then it can be avoided.
Now for plotting, stem is not really designed to plot multiple datasets next to each other, so we're going to have to cheat. It may be better to have each dataset in their own axis next to each other. Otherwise, we have to do something similar to TADA's answer. If you don't need each stom as a separate stem plot (ie. separate entry in legend) it's even simpler:
spacing = 50; %spacing between each storm stem plot.
fignames = fieldnames(LTA_stormplot_motions);
for figidx = 1:numel(fignames)
fname = fignames{figidx}; %current field we're working on (also figure title)
figure;
title(fname, 'Interpreter', 'none');
stormdata = {LTA_stormplot_motions.(fname)};
stormlength = cellfun(@length, stormdata);
stormstart = [1, cumsum(stormlength(1:end-1) + spacing)];
x = cell2mat(arrayfun(@(s, l) s:s+l-1, stormstart, stormlength, 'UniformOutput', false));
y = cell2mat(stormdata);
stem(x, y);
xticks(stormstart + stormlength / 2);
xticklabels(compose('storm %d', 1:numel(stormdata)))
end
Of course, with 76 plots side by side everything is squished together.
更多回答(1 个)
TADA
2019-1-25
I didn't use your data because I have no idea what you want from it
if exist('fig1', 'var') && ishandle(fig1)
close(fig1);
end
fig1 = figure(1);
k = 10;
n = randi(4, 1, k) + 2; % random mock n data points per storm
intervalBetweenStorms = 20;
for i = 1:k
x = (1:n(i)) + i*intervalBetweenStorms;
y = normrnd(10, 2, 1, n(i));
stem(x, y, 'b', 'Marker', 'none');
hold on;
end
xticks((1:k)*intervalBetweenStorms);
xticklabels(strcat('Storm ', cellfun(@num2str, num2cell(1:k), 'UniformOutput', false)));
0 个评论
另请参阅
类别
在 Help Center 和 File Exchange 中查找有关 Graphics Object Programming 的更多信息
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!