I was trying to find out, how to plot a cumulative distribution function (cdf) with specific x values but was not successful.
For example, if the dataset is:
x = [2.50 5.21 7.67 8.43 9.15 11.47 14.59 21.45];
y = [0.20 0.09 0.15 0.13 0.17 0.04 0.7 0.15]; % (total 1)
the graph shape definitely looks wrong, when I use y = cdfplot(x).
I also plotted the graph with cumsum(y) and x to check the shape and it looks fine, but I would like to know, if there is any code which plots cumulative distribution plots.
There's the stairs function for creating "stairstep graphs", which should be exactly what you want, incorporating your cumsum(y) idea.
Please see the following code snippet. I added two additional points for the start and end of some interval, here [0 ... 25]. Also, your values in y sum up to something larger than 1, so I modified these values, too.
x = [0 2.50 5.21 7.67 8.43 9.15 11.47 14.59 21.45 25];
y = [0 0.10 0.09 0.05 0.10 0.14 0.04 0.4 0.08 0];
stairs(x, cumsum(y));
xlim([-1 26]);
ylim([-0.2 1.2]);
That'd be the output (Octave 5.1.0, but also tested with MATLAB Online):
Hope that helps!
Related
I want to know how quickly some data returns to baseline after an initial peak (here at ca x=5);
The quadratic fit looks about right (from the figures option of matlab, shown below) - but I'm looking for a concise quantification of this curve, therefore I presume the 'decay rate' of the exponential function would be one very straightforward.
Is this assumption correct?
If yes, I looked at the formula on wiki for this, and attempted shamelessly to find a solve for the time constant (but unsuccessfully so). Can someone help me out, or is this actually a not so trivial problem?
edit: I was planning to find the peak using MathWorks' findpeaks() function, and the lowest point of the curve using the 'inverse' findpeaks() (as in: -y)
%approx data values of the curves below
y= [0 0.07 0.08 0.08 0.08 0.06 0.06 0.05 0.04 0.05 0.04 0.02 0.01 0.02 0.01 0.01 0.03 0.02 0.02 0.02 0.03 0.01 0.02 0.01 0.01 0.03 0.02 0.01 0.02 0.01];
x=1:numel(y);
plot(x,y);
These are the two options I was looking for, maybe someone can elaborate / improve this answer about the differences for these approaches - for me this is good enough, thanks for the comments. Before this step, using the data provided in the example of the question, the local maximum and minimum has to be extracted, this can be done easily using findpeaks()
approach 1) requires the curve toolbox from Matlab [Source]
%Fit a Single-Term Exponential Model, copy from Mathworks documentation, all credits go there
x = (0:0.2:5)';
y = 2*exp(-0.2*x) + 0.1*randn(size(x));
f = fit(x,y,'exp1')
f =
General model Exp1:
f(x) = a*exp(b*x)
Coefficients (with 95% confidence bounds):
a = 2.021 (1.89, 2.151)
b = -0.1812 (-0.2104, -0.152)
plot(f,x,y)
or approach 2) requires the optimizaion toolbox from Matlab [Source]
%copy from Mathworks documentation, all credits go there
rng default % for reproducibility
d = linspace(0,3);
y = exp(-1.3*d) + 0.05*randn(size(d));
fun = #(r)exp(-d*r)-y;
x0 = 4;
x = lsqnonlin(fun,x0)
plot(d,y,'ko',d,exp(-x*d),'b-')
legend('Data','Best fit')
xlabel('t')
ylabel('exp(-tx)')
Let's say we have
[x]=[0.1 0.2 0.3 0.4]
[y]=[0.25 0.30 0.40 0.55]
y1=diff(y)./diff(x)
y2=diff(y1)./diff(x)
And the result I get is
Matrix dimensions must agree
How do I solve this problem?
I redirect you towards this documentation. When you use the diff function, it will actually return you a vector with m-1 (m being its length), since what it does is output this:
diff(y1) = [y1(2)-y1(1) y1(3)-y1(2) ... y1(m)-y(m-1)]
As you can see, you will loose one value, and thus explaining your error. When you do your last line, it cannot divide diff(y1) by diff(x) since diff(y1) is equal to a vector of length 2 and diff(x) is equal to a vector of length 3.
Depending on what you want to do, you can change the code to the following :
[x]=[0.1 0.2 0.3 0.4]
[y]=[0.25 0.30 0.40 0.55]
y1=diff(y)./diff(x)
y2=diff(y1)./diff(x(1:end-1))
If you want to approximate the derivate of y, I really suggest you to take a look at the example in the page I linked. The matlab documentation always gives examples on how to use their functions, so go take a look. According to the documentation, if you want to calculate the partial derivate of the vector y, you need the step of your x vector.
x=[0.1 0.2 0.3 0.4]
y=[0.25 0.30 0.40 0.55]
x_step = 0.1
y1=diff(y)./x_step
y2=diff(y1)./x_step
x=[0.1 0.2 0.3 0.4] ;
y=[0.25 0.30 0.40 0.55] ;
dy = gradient(y)./gradient(x) ;
d2y = gradient(dy)./gradient(x) ;
I have some 2D points and I want to plot them in MATLAB such that every point has a different color and specifier. I have used plot function but it creates line whatever you give. I want to draw these points as discrete points only. How can I do that? Here is what I am trying to achieve in the simplest form (I used TikZ below):
UPDATE:
Thank you for your comments and answers, I have the following code right now:
x = [ 0.56, 0.4526, -0.4324, 0.2749, -0.2993, 0.3404, 0.1959, 0.3363, -0.1706];
y = [0.1999, 0.3939, 0.1999, 0.4414, 0.2000, 0.3931, 0.1999, 0.3966, 0.4056];
figure
plot(x(1),y(1),'rx')
hold on
plot(x(2),y(2),'*','Color','[0 0.9 0]')
hold on
plot(x(3),y(3),'*','Color','[0 0.5 0]')
hold on
plot(x(4),y(4),'o','Color','[0.47 0.52 0.8]','MarkerFaceColor','[0.47 0.52 0.8]')
hold on
plot(x(5),y(5),'o','Color','[0.05 0.28 0.63]','MarkerFaceColor','[0.05 0.28 0.63]')
hold on
plot(x(6),y(6),'s','Color','[1 0.71 0.30]','MarkerFaceColor','[1 0.71 0.30]')
hold on
plot(x(7),y(7),'s','Color','[0.9 0.32 0]','MarkerFaceColor','[0.9 0.32 0]')
%plot(x(7),y(7),'s','Color','[1 0 0.5]','MarkerFaceColor','[1 0 0.5]')
hold on
plot(x(8),y(8),'d','Color','[0.67 0.28 0.73]','MarkerFaceColor','[0.73 0.40 0.78]')
%plot(x(8),y(8),'d','Color','[0.67 0.28 0.73]','MarkerFaceColor','[0.67 0.28 0.73]')
hold on
plot(x(9),y(9),'d','Color','[0.29 0.08 0.55]','MarkerFaceColor','[0.29 0.08 0.55]')
xlabel('X')
ylabel('Y')
h = legend('(^1X,^1Y)','(^2X_1,^2Y_1)','(^2X_2,^2Y_2)','(^3X_1,^3Y_1)','(^3X_2,^3Y_2)','(^4X_1,^4Y_1)','(^4X_2,^4Y_2)','(^5X_1,^5Y_1)','(^5X_2,^5Y_2)');
set(h,'Location','best')
grid
I can now draw the points as dots with different colors and specifiers although this way may not be the best way.
You can simply specify the LineSpec option
http://fr.mathworks.com/help/matlab/ref/plot.html#inputarg_LineSpec
To obtain your example:
plot(xdata, ydata, '.')
Interpolate the following data into a smooth curve in the intervalš„ ā [ā2 4.9]. Plot the actual data and the interpolated curve on the same figure.
x| -2 -1.7 -1.4 -1.1 -0.8 -0.5 -0.2 0.1 0.4 0.7 1 1.3
y| 0.1029 0.1174 0.1316 0.1448 0.1566 0.1662 0.1733 0.1775 0.1785 0.1764 0.1711 0.1630
x| 1.6 1.9 2.2 2.5 2.8 3.1 3.4 3.7 4 4.3 4.6 4.9
y| 0.1526 0.1402 0.1266 0.1122 0.0977 0.0835 0.0702 0.0579 0.0469 0.0373 0.0291 0.0224
My current code is...but I'm having trouble doing the actual interpolated curve,would it help putting this data into an excel sheet? First time dealing with this.
close all
clear all
clc
x = [-2, -1.7, -1.4, -1.1, -0.8, -0.5, -0.2, 0.1, 0.4, 0.7, 1, 1.3, 1.6, 1.9, 2.2, 2.5, 2.8, 3.1, 3.4, 3.7, 4, 4.3, 4.6, 4.9];
y = [0.1029, 0.1174, 0.1316, 0.1448, 0.1566, 0.1662, 0.1733, 0.1775, 0.1785, 0.1764, 0.1711, 0.1630, 0.1526, 0.1402, 0.1266, 0.1122, 0.0977, 0.0835, 0.0702, 0.0579, 0.0469, 0.0373, 0.0291, 0.0224];
plot(x,y)
This post that I just recently answered pretty much solves your problem. However, I'll throw you a bone and help you out. Use interp1 to do this interpolation for you. What you do is you specify the (x,y) control points, which are those points that are part of your dataset, then you specify a slew of other x points, which have more granularity and have values in between those values of the original x values that you originally specified, and you can see what the output is.
Here are the steps you'd need to perform to do this interpolation:
Define your (x,y) points (which is what you have already done).
Define a grid of x points that are further granular in comparison to what you have. You would specify x values that are in between the original x values that you have. Use linspace to generate a set number of points in between a minimum and maximum... which in your case is -2 and 4.9 respectively. We can hide this away by using min and max on your x points so that you can adapt this to any dataset you want to use.
Use interp1 with the grid of points in step (2) and find the interpolated y points.
Plot the points.
What I'm going to do is do the above procedure, then produce a plot where I'll draw what the original points that were given, as well as a dashed line that shows the interpolated curve. I'm also going to use spline interpolation to smooth out any irregularities.
As such:
%// Define your points - Step #1
x = [-2 -1.7 -1.4 -1.1 -0.8 -0.5 -0.2 0.1 0.4 0.7 1 1.3 1.6 1.9 2.2 2.5 2.8 3.1 3.4 3.7 4 4.3 4.6 4.9];
y = [0.1029 0.1174 0.1316 0.1448 0.1566 0.1662 0.1733 0.1775 0.1785 0.1764 0.1711 0.1630 0.1526 0.1402 0.1266 0.1122 0.0977 0.0835 0.0702 0.0579 0.0469 0.0373 0.0291 0.0224];
%// Step #2 - Define grid of x points - Define 100 points in between min and max
xval = linspace(min(x), max(x), 100);
%// Step #3 - Use interp1
yval = interp1(x, y, xval, 'spline');
%// Step #4 - Plot the stuff
plot(x, y, 'bo', xval, yval, 'r--');
%// Throw in a grid too
grid;
This is the plot I get:
Cool?
I would like to generate the X value using a corresponding random Y value, these random values are within the range of Y, from a graph which i have created using the pchip function, but i want the generated X value to stay within a specific range.
My code:
samples=10
r=rand(samples,1)
Y=[0.93 0.94 0.95 0.96 0.97 0.98 0.99 1];
x=12.5:45:327.5;
angle=pchip(y,x,r);
Output:
angle =
1.0e+03 *
-0.1392
-3.3718
-3.4856
-3.2264
-0.5284
-0.8114
-2.2368
-0.0804
-2.9240
-1.9510
I would like the values to lie between -12.5-360 and I believe I could use something like this:
Y=[0.93 0.94 0.95 0.96 0.97 0.98 0.99 1];
x=12.5:45:327.5;
xi=-12.5:360;
angle=pchip(y,xi,x);
But I cant then get it to generate the required X value from the given Y value.
I have tried the following but it does not work:
samples=10
r=rand(samples,1)
Y=[0.93 0.94 0.95 0.96 0.97 0.98 0.99 1];
xi=-12.5:360;
x=12.5:45:327.5;
angle=pchip(y,xi,x,r);
I have looked at the mathworks pchip article and other mathworks articles but they don't seem to solve my problem and also looked at this stackoverflow article How can I ask matlab to give me the value of y if I input the value of x?, which wasn't the solution needed.
Thanks for your time and help you can offer.
Edit 1 - A little more information
I think what would solve my problem is if I could get the pchip function just to interpolate my data between to set points a max and min. As TryHard pointed out maybe the data is been interpolated outside the data which has been defined causing instabilities.
I know that I can interpolate within a certain range as I demonstrated above but I want to be able to do this and generate the X values given the Y values in the vector r
Try constraining the values of r to the observed range of y:
samples=10;
y=[0.93 0.94 0.95 0.96 0.97 0.98 0.99 1];
x=12.5:45:327.5;
r=rand(samples,1)*(max(y)-min(y)) + min(y);
angle=pchip(y,x,r);