How to plot discrete data in a stackedplot

I'd like to plot timetable data consisting of discrete data (e.g. boolean, enumerations) in a stackedplot (common time x-axis).
In order to plot discrete data there are functions like stairs which supress (?) linear interpolation and plot like interpolation method "zoh".
Is it possible to change the interpolation of stackedplot (to "zoh") or a similar plot with time cursor (lets call it stackedstairs) ? Or do I have to use multiple subplots with stairs and link the x-axis?

 Accepted Answer

dpb
dpb on 29 Mar 2021
Edited: dpb on 29 Mar 2021
There's a 'PlotType' property in the stackedplot object that has the option for 'stairs' -- none of the previous gyrations are needed, simply
hSP=stackedplot(tbl,vars); % stacked plot for starters
set(hSP.LineProperties,{'PlotType'},{'stairs'})
Have to use set since there is an array of axes and the dot notation can't deal with arrays.

More Answers (1)

dpb
dpb on 26 Mar 2021
Edited: dpb on 26 Mar 2021
You can get creative and use stackedplot to create the axes for you, and then go "handle-diving" to find and modify the content of the underlying axes...
I used one of the examples for stackedplot as a start point --
tbl = readtable('patients.xls'); % some sample data
vars={'Height','Weight','Systolic','Diastolic'}; % pick the variables
hSP=stackedplot(tbl,vars); % stacked plot for starters
hAx=flip(hSP.NodeChildren(numel(vars)+1:end)); % get the axes handles
for i=1:numel(hAx) % for each axes (same as numel(vars))
hold(hAx(i),'on') % set hold on for each axes to keep other properties unchanged
hL=hAx(i).Children; % get existing line handle
delete(hL); % delete that line
hSL(i)=stairs(hAx(i),tbl.(vars{i})); % replace with stairs line
end
Above yields
Introducing a function handle for the plot function into stackedplot seems worthwhile enhancmenet request.
NOTA BENE: The stackedplot object hides the axes handles in the undocumented and hidden NodeChildren property. Another case IMO of TMW getting far too clever in their penchant to create opaque objects.
Inspection showed the Axes are the last elements in the array and are stored in obverse order of their creation; this is a pretty common (universal?) order in such case; one can tell which is which by inspection of the .Position property for the bottom location of the axes. Remember the position 4-vector is [left bottom width height]

11 Comments

Edited to fix 1 typo:
hSP=stackedplot(tbl,)
% ^ removed
BTW, to access the axis handles without returning other NodeChildren (e.g. Legend handles),
hAx = flip(findobj(hSP.NodeChildren, 'Type','Axes'))
The typo correction should be
hSP=stackedplot(tbl,vars);
% ^ plot only the listed vars
I created the vars variable to shorten the for loop and then didn't patch up the copied code to match...if use whole table will get a bunch more variables than the above four.
The enhancement to find the axes handles is good, I can never recall exact syntax for findobj or otomh.
Thanks for the answer, unfortunately the example does not work for me. I have trouble deleting the old line. After deleting, I receive following warning in the command window. This also results in a 'broken' stackedplot: no 'subplots' and no common data cursor. The behaviour without deleting seems to work as intended (except of course now there is a plot line and also a stairs line).
Warning: Error updating StackedLineChart.
Invalid or deleted object.
Could you show us what's in hL and hAx?
Seeing the relevant section of your code would also help.
I already get the error with the example code snippet postet by dpb above.
dpb
dpb on 29 Mar 2021
Edited: dpb on 29 Mar 2021
All the code and error messages in context.
Which release are you using? Something after R2019b? It's possible TMW locked down something in a later release, but I'd guess you've got a typo and are referencing an already deleted line handle inadvertently.
NB: I deleted the line handle and the created a new array to hold the stacked-plot new handles...if one reused the same variable name, it would be very easy to wipe that array out and end up having/trying to reference an invalid handle.
Well the screenshot above is from R2019b, but same behaviour with R2019a and the new R2021a for me. I cleared the workspace entirely before running the script (so there should not be any problems with existing variables). Code is copy/pasted, so no typos either?!
Found a workaround: instead of deleting the old line, I just set the linestyle to none after the loop. This only affects the 'old' lines, not the 'stairs'.
set(hSP,'LineStyle','none');
This is bizzaro...If I just paste the code in, it errors here, as well.
But the following session is what I did at command line interactively and it still works as it did and generates the figure attached. There's something different between running the interactive code and pasting it; at this point I've no idea what nor why.
Here's the log of the session---identical code just retrieved line-by-line at command line to build the for...end loop before the CR to execute after the end was entered. I stuck in the disp(i) just in case to see which loop it error'ed on if it did...
>> clear hSP hAx hL
>> hSP=stackedplot(tbl,vars); % stacked plot for starters
>> hSP
hSP =
StackedLineChart with properties:
SourceTable: [100×10 table]
DisplayVariables: {'Height' 'Weight' 'Systolic' 'Diastolic'}
XVariable: []
Color: [0 0.4470 0.7410]
LineStyle: '-'
LineWidth: 0.5000
Marker: 'none'
MarkerSize: 6
Show all properties
>> hAx=flip(hSP.NodeChildren(numel(vars)+1:end)); % get the axes handles
>> hAx
hAx =
4×1 Axes array:
Axes
Axes
Axes
Axes
>> for i=1:numel(hAx) % for each axes (same as numel(vars))
hold(hAx(i),'on') % set hold on for each axes to keep other properties unchanged
hL=hAx(i).Children; % get existing line handle
delete(hL);
hSL(i)=stairs(hAx(i),tbl.(vars{i})); % replace with stairs line
disp(i)
end
1
2
3
4
>>
My former post was to simply take the above command window and put it into the Answer and clean it up a little -- little suspecting there would/could be any difference in result.
I'm at a loss to explain the difference; some internal race condition on updating the properties between what the JIT interpreter does between a code segment seen all at once versus entered line-by-line interactively, maybe?
I've no explanation, can only suggest to try to write the code serially instead of in the loop as a possible workaround unless somebody else can delve into the bowels and find a root cause.
I created a minimal example to reproduce this error. Run as a script, not in command window.
clear;figure(1);clf;
tbl = readtable('patients.xls');
vars={'Height','Weight','Systolic','Diastolic'};
hSP=stackedplot(tbl,vars);
hAx=flip(hSP.NodeChildren(numel(vars)+1:end));
for i=1:numel(hAx)
hold(hAx(i),'on')
hL(i)=hAx(i).Children; %save hL to array
% delete(hL); %don't delete here
hSL(i)=stairs(hAx(i),tbl.(vars{i}));
end
pause(1); %comment/uncomment this line for race condition(?)
delete(hL); %delete the whole array
The pause here seems to be the key. In interactive mode you always have a little pause.
The code above does produce the correct figure but you lose the common data cursor!
So to summarize this up: instead of deleting, I just set the linestyle to none, as mentioned above.
Thanks for your help!
dpb
dpb on 29 Mar 2021
Edited: dpb on 29 Mar 2021
" I just set the linestyle to none after the loop."
You can do that first instead of last to make them not show. Of course, that leaves the old data in place as well, but "any port in a storm!" when it comes to workarounds.
However, see the alternate Answer for the REAL workaround -- but your above reference got me looking more deeply at the stackedplot object and turns out TMW had it built-in all along -- and it is even documented in an example, I just didn't look at all the examples.

Sign in to comment.

Categories

Find more on Creating, Deleting, and Querying Graphics Objects in Help Center and File Exchange

Products

Release

R2021a

Asked:

on 26 Mar 2021

Edited:

dpb
on 29 Mar 2021

Community Treasure Hunt

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

Start Hunting!