I have trouble changing the x-range (XLim) in plots of curve-fit objects.
Preparing a Minimal Example
Let's define noisy data and fit a function to it, using fit from the curve fitting toolbox.
xdata = (0:0.1:1)';
noise = 0.1*randn(size(xdata));
ydata = xdata.^2 + noise;
f = fittype('a*x.^2 + b');
fit1 = fit(xdata, ydata, f, 'StartPoint', [1,1]);
fit1 is now a cfit object and we can plot it using its (overloaded) plot method:
plot(fit1, xdata, ydata)
The Problem
When we now change the XLim of the plot using set(gca, 'XLim', [0,2]), the plot updates but the fit curve is not extended. The documentation suggests that you can do that automagically from within the plot command, but for it does not work for me:
plot(fit1, xdata, ydata, 'XLim', [0, 1])
-> Subscript indices must either be real positive integers or logicals.
-> Error in cfit/plot (line 228)
-> handles = plot(xpoints(~outliers),ypoints(~outliers),S2,...
If I use cftool for the fit (a GUI wrapper for fit), I can enter XLim under Tools->Axes Limits. The fit function is then displayed for the whole range. How can I do this programmatically?
I am aware that you can evaluate the fit function for a given range, but when you have to do that for confidence intervals and several fits, this becomes tedious. I am looking for an easier way, and I think I am just uing the plot command wrong.
The documentation says that when you plot a fit object, it will extrapolate to the current axis limits. It does not redraw the line after you change the plot limits. Further, it appears that when you overload plot it plots the fitdata as the same length as the xdata/ydata. To accomplish your goal, you could do
figure; hold on
plot(xdata,ydata,'.')
ext_xdata = 0:0.1:2;
plot(ext_xdata,fit1.a*ext_xdata.^2 + fit1.b,'r')
But you alluded that the above solution is undesirable for you because of complications of your application. An alternative approach is
figure; hold on
plot(xdata,ydata,'.')
set(gca,'xlim',[0, 2]);
plot(fit1)
This isn't a one line solution like what you seem to be looking for, but it removes the need to specify a new xrange.
The function plot that you use to plot a fit object actually overloads the standard plot function. If you try to set a breakpoint if error (dbstop error), you would see that the actual matlab plot function is called inside the function plotting a fit object. The syntax is then not exactly the same which means that you need to call either xlim([minLim,maxLim]); after you have plotted the function
plot(fit1,xdata, ydata);
xlim([minLim,maxLim]);
I am not sure why this happens since in matlabs documentation they actually state that it should work. This may be a bug which should be reported.
Related
I have a geographically distributed data set with X-coordinate, Y-coordinate and corresponding target value of interest D. That is, my data set consists from three vectors: X, Y, D.
Now what I would like to do, is interpolate and extrapolate the target variable D over a coordinate grid of interest. The griddata-function in Matlab seems to be able to help me in this problem, but it only does interpolation over the convex hull determined by my data set.
What I would like to do, is to also extrapolate the data D to any rectangular coordinate grid of interest like so:
I have tried using functions like interp2 and griddedInterpolant, but these functions seem to require that I provide the known data as monotonic matrices (using e.g. meshgrid). That is, if I have understood correctly, I must provide X,Y,D as 2D-grids. But they are not grids, they are non-monotonic vectors.
So how can I proceed?
You can use griddata with option 'v4' that uses biharmonic spline interpolation.
Unlike the other methods, this interpolation is not based on a triangulation.
Other option is using scatteredInterpolant. You can choose to use any of 'linear' or 'nearest' methods for extrapolation
I found out one way using scatteredInterpolant:
xy = -2.5 + 5*gallery('uniformdata',[200 2],0);
x = xy(:,1);
y = xy(:,2);
v = x.*exp(-x.^2-y.^2);
F1 = scatteredInterpolant(x,y,v, 'natural');
[xq,yq] = ndgrid(-5:.1:5) % Make the grid
vq1 = F1(xq,yq); % Evaluate function values at grid of interest
surf(xq,yq,vq1)
hold on
plot3(x,y,v, 'ro', 'MarkerFaceColor', 'red')
xlabel('X')
ylabel('Y')
zlabel('V')
title('Interpolation and exrapolation based on scattered data')
The problem is, you can do extrapolation with only three methods: 'linear', 'nearest', 'natural'.
I want to make two line plots Ckkk and Ckk appear on the same plot. The above error keeps occurring. I've checked with similar problem and none of the fixes have helped.
The code is as below
function cancer()
clear all;
clc;
t0=0;tend=60;nt=tend;
dt=(tend-t0)/(nt-1);
t=t0:dt:tend;
mambda=0.75;nambda=0.50;lambda=0.25;phi=0.0;psi=0.0;
%nu cell kill strength
%nu=zeros(length(t));
%inu= find(t>=40);
%nu(inu)=0.12;
%mu cell kill strength
%mu=zeros(length(t));
%inu = t>=40;
%mu(inu)=0.22;
%lu cell kill strength
%lu=zeros(length(t));
%inu= t>=40;
%lu(inu)=0.32;
C(1)=100;Ca=100;Cb=100;Ct=100;
Ctt=100;Cttt=100;Cx=100;Ckk=100;Ck=100;Ckkk=100;K(1)=300;
for i=1:length(t)-1
%Equation ?c
Cx(i+1)=Cx(i)+dt*(lambda*Cx(i));
%Equation ?c(1-c/K)with different ? values.
Ck(i+1)=Ck(i)+dt*(lambda*Ck(i)*(1-(Ck(i)/K(i))));
Ckk(i+1)=Ckk(i)+dt*(nambda*Ckk(i)*(1-(Ckk(i)/K(i))));
Ckkk(i+1)=Ckkk(i)+dt*(mambda*Ckkk(i)*(1-(Ckkk(i)/K(i))));
%Gompertz Growth Equations with different ? values.
C(i+1)=C(i)+dt*(-lambda*C(i)*log(C(i)/K(i)));
%Anti-tumor treatment induces a tumor cell kill with strength 0?nu?1.
%Ct(i+1)=Ct(i)+dt*(-lambda*Ct(i)*log(Ct(i)./K(i)))-nu(i).*Ct(i);
%Anti-angiogenic treatment
K(i+1)=K(i)+dt*(phi*C(i)-psi*K(i).*((C(i)).^(2/3)));
When I call the plot function, Error on plot occurs
plot(Ckkk,'b',Ckk,'r');
xlabel('Time In Days')
ylabel('Number of Cells')
end
Just like the error says, you need to specify the X coordinates if more than a single matrix of Y coordinates is provided. In your case, you have two, Ckkk and Ckk. If you need to plot those as two independent variables, one solution is below
figure; clf;
plot(t, Ckkk,'b', t,Ckk,'r');
Another solution is
figure; clf;
hold on;
plot(t, Ckkk,'b');
plot(t, Ckk,'r');
hold off;
In the later, you can actually skip t, because you are providing a single Y matrix to each plot function.
It is generally a good idea to check the documentation before you post a question here.
I have a set of curves varying over time, that are stored in a MATLAB matrix. Each row of the matrix is one of those curves, unfolding over time. Those are repetitions of a random experiment.
I need to plot the mean of these curves over time, along with the 95% confidence intervals.
My understanding of statistics this is rather poor, but I was suggested to use bootstrap confidence intervals using MATLAB's bootci function.
I implemented a minimal example in MATLAB, but I have some doubts. I hope you can help me gaining a better grasp on this and avoiding dumb mistakes.
Here's the example:
NVARIABLES = 200;
NOBSERVATIONS = 1000;
RESAMPLING = 10000;
DATA = rand(NOBSERVATIONS, NVARIABLES);
[CI, STAT] = bootci(RESAMPLING, #mean, DATA);
MEAN = mean(DATA); % <------- [1]
x = 1:NVARIABLES;
figure;
hold on;
plot(x, MEAN, 'LineWidth', 2);
plot(x, CI(1,:), '--', 'LineWidth', 2); % [2]
plot(x, CI(2,:), '--', 'LineWidth', 2);
% plot(x, MEAN-CI(1,:)); % ?
% plot(x, MEAN+CI(2,:)); % ?
hold off;
Here are my questions:
Am I using the function properly?
When reporting/plotting the mean, is it correct to plot mean(DATA) (see line 1) or I should plot a mean derived by the bootstrapping procedure? I saw that STAT contains the mean for each bootstrap example, but I don't know whether I should use this information, and how
Is it correct to plot the confidence intervals the way I am doing (see line [2]), or I should plot MEAN-CI(1,:) and MEAN+CI(2,:)?
Please find attached the plot generated by the code.
I can answer Q1 and Q3.
Q1. The first argument needs to be the number of bootstrap samples used in the computation, the second, a function that returns the statistic for which you wish to find the confidence intervals, and the third is the dataset itself that you want to give as input to the function. You will have to ensure if the first argument is correct for you, the rest seems correct.
Q3. What you've done is right - CI gives the range, and not the variation from the mean. There's also another way to plot it, which might be better in certain scenarios, or just based on personal preferences. plot_ci is a function that lets you plot confidence intervals and shows clean patches for these intervals on the same plot. The plots look like this (this is a sample plot, not based on the dataset in the question):
Here's the command:
plot_ci(x,[MEAN,CI(1,:),CI(2,:)],'PatchColor', 'k', 'PatchAlpha', 0.1, 'MainLineWidth', 2, 'MainLineStyle', '-', 'MainLineColor', 'b','LineWidth', 1.5, 'LineStyle','--', 'LineColor', 'k');
I have a vector with 1000 random numbers called v. I also have a vector, called x that represents the domain of which the numbers in v are generated, and another vector y that has the numbers of the cdf of the values in v. I know that I can do plot(x,y); and get a smooth function of the (non-empirical) cdf, and I also know that I can do cdfplot(v) to get a function of the empirical cdf.
My question is: How can I get these plots on the same set of axis?
Thank you for your help.
You could either generate data for an empirical cdf plot using ecdf or plot it directly with cdfplot like you mentioned. I would recommend using cdfplot since it sets up a few more things, such as a grid:
hFig = figure;
cdfplot(v);
hold all;
plot(x, y);
And as a bonus! Consider showing the X axis in logarithmic units, whichever reveals the data the best for you:
hAxes = get(hFig, 'CurrentAxes');
set(hAxes, 'XScale', 'log')
So, I've fitted an exponential curve to some data points using 'fit' and now I want to get the equation of the fitted curve in the Legend in the graph. How can I do that? I want to have an equation on the form y=Ce^-xt in the legend. Can I get the coefficients, C and x from the fitted curve and then put the equation inside the legend? Or can I get the whole equation written out in some way? I have many plotted graphs so I would be grateful if the method is not so much time consuming.
Edit: Perhaps I was unclear. The main problem is how I should get out the coefficients from the fitted line I've plotted. Then I want to have the equation inside the legend in my graph. Do I have to take out the coefficients by hand (and how can it be done?) or can Matlab write it straight out like in, for example, excel?
The documentation explains that you can obtain the coefficients derived from a fit executed as c = fit(...), as
coef=coeffvalues(c)
C=coef(1)
x=coef(2)
You can create your own legend as illustrated by the following example.
Defining C and x as the parameters from your fits,
% simulate and plot some data
t= [0:0.1:1];
C = 0.9;
x = 1;
figure, hold on
plot(t,C*exp(-x*t)+ 0.1*randn(1,length(t)),'ok', 'MarkerFaceColor','k')
plot(t,C*exp(-x*t),':k')
axis([-.1 1.2 0 1.2])
% here we add the "legend"
line([0.62 0.7],[1 1],'Linestyle',':','color','k')
text(0.6,1,[ ' ' num2str(C,'%.2f'),' exp(-' num2str(x,'%.2f') ' t) ' ],'EdgeColor','k')
set(gca,'box','on')
Example output:
You may have to adjust number formatting and the size of the text box to suit your needs.
Here is a piece of code that will display the fitted equation in the legend box. You can reduce the amount of digits in the legend by manipulating the sprintf option: %f to %3.2f for example.
%some data
load census
s = fitoptions('Method','NonlinearLeastSquares','Lower',[0,0],'Upper',[Inf,max(cdate)],'Startpoint',[1 1]);
f = fittype('a*(x-b)^n','problem','n','options',s);
%fit, plot and legend
[c2,gof2] = fit(cdate,pop,f,'problem',2)
plot(c2,'m');
legend(sprintf('%f * (x - %f)^%d',c2.a,c2.b,c2.n));
The command disp(c2) will display in the command window what is stored in the fit object. Also, by enabling the "datatip in edit mode" option (Matlab preferences, then Editor, then Display), you will have an instant view on the data stored by putting your mouse cursor over an object.
function [S]=evaFit(ffit)
S=sprintf('y=%s',formula(ffit));
S2='';
N=coeffnames(ffit);
V=coeffvalues(ffit);
for i= 1:numcoeffs(ffit)
S2=sprintf('%s %c=%f',S2, string(N(i)), V(i));
end
S=sprintf('%s%s',S, S2);
end