Multiple plots failing can't scale y'y axis properly

So, I have created and saved into a `.mat` file a struct called `struct_scenarios(2).a(15000,1)`. In a new script I am trying to manipulate the data, plot a histogram then a cdc, using `cdfplot`, for each struct member. I am facing the following problems (easily seen in the sample picture): What i was basically thinking to do was write a `for` to iterate through the struct. In this case 2 struct members.
So I thought to plot:
1st iteration the 1st hist and its CDF plot.
2nd iteration the 2nd hist and its CDF plot.
My problem is that the CDF plots aren't there (green spots in the bottom of the picture) since the y'y axis is there to measure the frequency of the histograms and its scale is not [0,1]. Any ideas?
The code:
clear all;
close all;
clc;
load('struct_scenarios.mat');
number_of_files = length(scenario_store);
%# Preparing the global histogram
m_min_global = floor(min(min(scenario_store(:).a))); % Global min of the N scenarios
m_max_global = ceil(max(max(scenario_store(:).a))); % Global max of the N scenarios
binranges = m_min_global:m_max_global;
nbins = length(binranges);
cmap = hsv(number_of_files);
binEdges = linspace(m_min_global,m_max_global,nbins);
for plot_number=1:number_of_files
%# Preparing the local histogram
m_min_local = floor(min(scenario_store(plot_number).a)); % Local min of the N scenarios
m_max_local = ceil(max(scenario_store(plot_number).a)); % Local max of the N scenarios
binranges = m_min_local:m_max_local;
%nbins = length(binranges);
%binEdges = linspace(monte_min_global,monte_max_global,nbins);
aj = binEdges(1:end-1); % Bins lower edge
bj = binEdges(2:end); % Bins higher edge
cj = (aj+bj)./2;
cj = cj';
[~,binIdx] = histc(scenario_store(plot_number).a,[binEdges(1:end-1) Inf]); % Assign values to bins
nj = accumarray(binIdx,1,[nbins-1 1],@sum); % Count number of values in each bin
f_plot = figure(1);
p1 = bar(cj,nj,'hist'); % Plot hist
set(gca, 'XTick',binEdges, 'XLim',[binEdges(1) binEdges(end)],'Box','off');
set(p1,'FaceColor',cmap(plot_number,:),'EdgeColor','w','facealpha',0.8);
hold all;
[h,stats] = cdfplot(scenario_store(plot_number).a);
set(findobj('Type','line'),'Color','g','LineWidth',1.2);
hold all;
end
The image:

Answers (2)

...the CDF plots aren't there ... since the y'y axis is there to measure the frequency of the histograms and its scale is not [0,1]. Any ideas?
Yeah
doc plotyy % put the CDFs on the other axis

2 Comments

would you care to produce some code? Because frankly i don't see your point..
Well, phooey... cdfplot isn't very cooperative in playing well w/ other plotting (as in it's downright rude :( ). I'll have to play a little more than I had thought to get a working example.
But, the idea is that plotyy puts a second y-axis on the RHS of the plot w/ a different y scale such that your cdf lines will also have a reasonable scale and thereby show up.
I'll try to get a minimal demo here this evening if I can get a few minutes to do so. It looks like the simplest way to get there may be to simply compute the empirical cdf values outside the prepackaged plotting routine and plot them directly but I'll look at what caused the grief I had in my first attempt directly a little more before committing to a direction.
Meanwhile, perhaps the idea of the other axis will give you enough to go on and you may beat me to the finish line.

Sign in to comment.

dpb
dpb on 13 Mar 2014
Edited: dpb on 13 Mar 2014
OK, here's a starting point...
x=(randn(300,1)); % some sample data
[N,X]=hist(x); % used hist() so didn't have to fool w/ edges
hA=plotyy(X,N,x,nan,@bar,@mycdfplot); % plot both on separate y axes
set(hA(1),'ytick',[0:10:100]) % do a little fancying up
set(hA(2),'ytick',[0:0.10:1])
grid on
I created a new function to use as plotyy requires two arguments and trying to clean up after creating the two axes with the RH axes empty of data doesn't work well with the built-in cdfplot function because unlike plot it won't accept an optional axes handle on which to do its thing but demands top billing.
The substitute function is pretty simple...
function hL = mycdfplot(x,dmy)
% CDFPLOT(X,DMY) plots an empirical cumulative distribution
% of the observations in x. DMY is a dummy unused variable
% to be compatible in argument count with PLOT.
%
% H = CDFPLOT(X,DMY) returns the handle of the line object of
% the above ECDF.
%
% Substitute for CDFPLOT that can be called by PLOTYY which
% requires a consistent interface with PLOT of PLOT(X,Y)
% Solely for use in overlaying the CDF with a histogram or
% other plot style on 2nd axis.
%
% Removes the other labeling and refinenments to plot of PLOTCDF
% so can customize as wish to match style desired for the dual
% plotting.
[yy,xx] = cdfcalc(x);
% Create vectors for plotting
k = length(xx);
n = reshape(repmat(1:k, 2, 1), 2*k, 1);
xCDF = [-Inf; xx(n); Inf];
yCDF = [0; 0; yy(1+n)];
hCDF = plot(xCDF , yCDF);
if (nargout>0), hL=hCDF; end
end
Simply cut 'n paste into a new m-file, rename to your suiting if so choose and happy hunting!
When you get to wanting to use histc and some options there, use a "trick" Steven Lord showed me just a few days ago I hadn't thought of doing to pass optional arguments to routines used in plotyy which doesn't know what to do with them.
The following is from a thread in cs-sm newsgroup where the poster wanted arguments to the fill function when using it with plotyy. Steven demonstrates that as well as another parameter with the basic plot function. Modify the idea to fit your needs for histc and anything else you want with the custom mycdfplot.
> How can I pass an argument to fill, either as a function handle or a string?
Anonymously using an adapter.
% Sample data
X1 = 0:0.1:2*pi;
Y11 = sin(X1);
Y12 = cos(X1);
Y2 = Y11+Y12;
plotyy([X1 fliplr(X1)], [Y11 fliplr(Y12)], ... % Data for first plot
X1, Y2, ... % Data for second plot
@(X, Y) fill(X, Y, 'r'), ... % Function to use for first plot
@(X, Y) plot(X, Y, 'k', 'LineWidth', 5)); % Function to use for second plot
After doing the FILL I'd originally just used @plot as the 6th input argument, but the thin blue line on the red background was hard to see. So I changed the color and made the line a bit thicker.
PLOTYY requires the functions you specify as the 5th and 6th inputs to accept just two inputs, and the anonymous functions in those locations do. FILL requires you to call it with three input arguments, and the anonymous function does. PLOT doesn't require any additional arguments, but the anonymous function passes some optional input arguments into PLOT anyway.

1 Comment

ADDENDUM:
I don't have time to really build a full reproduction of your at the moment sorry but got to thinking that for your case you'll want to use plotyy first saving the axes handles. Then for the second and subsequent, you can use histc and mycdfplot directly with the LH and RH axes the target. NB: that hold does not take a vector of handles so you'll need to be sure to use it on each axis in turn to avoid replacing the first.
It's not as daunting as it may seem...or, of course, you can go to the section under the Graphics chapter in the documentation on using multiple axes and build the RH axes object yourself directly and avoid plotyy entirely. I generally just let it build the two for me and mung until I'm happy.

Sign in to comment.

Asked:

on 12 Mar 2014

Commented:

dpb
on 13 Mar 2014

Community Treasure Hunt

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

Start Hunting!