According to Matlab's help, quantile interpolates linearly between points on the empirical cumulative distribution function (ECDF). Importantly, the points interpolated between are the mid-points of the risers at each step. I'm finding the actual behaviour to be significantly different. Here is my example, the ECDF, and a line segment to show the interpolation:
y= [ 1 2 5 5 5 5 5 5 9 10 ]
ecdf(y)
grid on
set(get(gca,'Children'),'LineWidth',2)
hold on
% Line segment for interpolation
x2points=[2;5]; y2points=[0.15;0.5];
plot(x2points,y2points)
From the interpolation line segment, we would expect the quantile for F(x)=0.3 to be around x=3.3, but instead, it is x=5.
yInterior=0.3 % Value to get `x` for
xInterior=interp1(y2points,x2points,yInterior) % ans = 3.2857
xInterior=quantile(y,yInterior) % ans x=5
Is there another piece of documentation elsewhere that I'm missing which explains this difference?
Am I the only one seeing this?
I'm using Matlab 2015b.
Related
i've defined each function alone and plot it then made the addition of the functions then plot them all together using subplot .
%with using heaviside
clc;clear
t=-5:1/1000:+5
u1=heaviside(t-2)
u2=heaviside(t+1)
u3=heaviside(t+4)
X=u1+u2+u3
subplot(411)
plot(t,u1,'r');grid on
subplot(412)
plot(t,u2,'r');grid on
subplot(413)
plot(t,u3,'r');grid on
subplot(414)
plot(t,X,'r');grid on
In your case, X is the sum of 3 heaviside functions with different time-shifts, meaning it has a total value of 3*1 (for t to infinity).
If you want the 3 step function X to have an amplitude of 1, you have to divide by 3.
clc;clear
t=-5:1/1000:+5;
u1=heaviside(t-2);
u2=heaviside(t+1);
u3=heaviside(t+4);
X=(u1+u2+u3)/3;
This question already has answers here:
How to have square wave in Matlab symbolic equation
(3 answers)
Closed 6 years ago.
I have a vector T that is defined as
T=zeros(1,4)
I want to define T such that T(1) and T(2) are equal to 1 and T(3) and T(4) are equal to 0. So that when I plot T it looks like a square wave.
I have tried
for i=1:2:size(T,2)
T(i:i+1)=1
end
figure; plot(T);
But this does not give the desired result. It turns out to be [1,0,1,0].
What is the right way to do this assignment?
To differentiate from questions about plotting square waves:
I wanted to find out how exactly to create the loop that would plot to look like a square wave, without explicitly defining frequency or using the symbolic equation. I would then use this information to modify another script that would do the same thing but a larger vector T where the "period" is not the same. Sometimes it is 11s, sometimes 9s and so on.
The period is 4, not 2:
for i=1:4:size(T,2)
T(i:i+1)=1
end
figure; plot(T);
If you have access to the signal processing toolbox, an alternative is using the square function:
T = (1+square(0:pi/2:3*pi/2))/2 %// 1 1 0 0
I've tried to plot cdfcurves of my data by calling cdfplot(x) function. Here is part of my code:
figure;
for i=1:length(num_curves)
h = cdfplot(10*log10(plot_vec1(:,i)));
set(h,'Linewidth',2,'Color',cc(i,:),'Linestyle','-');
hold on
%set(color, cc(i,:));
end
Unfortunately the result I get is very confusing.
Yellow and purple curves are starting from nonzero value, but CDF curve should always start from zero!
Can anyone give me some suggestions? I've tried to plot yellow curve by itself, but it is still 'biased'.
Thank you for help!
The problem is that your data plot_vec1 contains zeros. Those zeros are transformed to -inf when you transform to dB with 10*log10(). Then cdfplot sees that the minimum finite value (about -67 in your yellow curve) has many samples (with value -inf) below it. That's why it gives a non-zero accumated probability there.
For example, compare these two figures
Normal case, all values are finite:
cdfplot([1 2 3 4 5 6])
Some values are -inf:
cdfplot([-inf -inf 3 4 5 6])
Here the minimum finite value, which is 3, has a 0.33 cumulative probability shown on the vertical axis. That's because 2 of the 6 samples are - inf and are thus below 3:
Possible workarounds: remove those zeros before applying the logarithm, or replace the resulting -inf by a very small value in dB, such as -100.
This question already has answers here:
Weighted random numbers in MATLAB
(4 answers)
Closed 7 years ago.
I have to generate a random variable that ranges from 20 to 30,
with 0.1 interval,
and the pmf of it is given by 1x101 matrix (for x=20, 20.1, ... 29.9, 30).
Now I have to make random variable with this given pmf,
But all I know about generating R.V is something related to gaussian, or uniformly distributed function.
So is there any way to implement generating random variables with arbitrary pmf?
I think this should do the trick.
%// First I created some random data
N=1e6;
x=randn(1,N);x=(x-min(x))/(max(x)-min(x));
pmf=hist(x,101)./N;
%// It's a normal distribution but scaled to output to [0 1]
%// First, get the cdf
xh=cumsum(pmf);
%// Create the list of possible values of this random variable
Y=20:.1:30;
%// Create a uniformly distributed random variable between 0 and 1
R=rand()
%// Find where the cdf value is closest to R
[~,J]=min(abs(xh-R));
%// Find the resulting sample values
Y(J)
%// Just a little plot to make sure it's working
hold on
plot(Y,xh)
plot([20 30],[R R],[Y(J) Y(J)],[0 1])
hold off
I think what you are trying to do is multinomial sampling, see http://se.mathworks.com/help/stats/mnrnd.html?refresh=true
If you just want one sample, you can (crudely) do something like
find( mnrnd(1,pmf))
where pmf is the vector of probabilities (assert(sum(pmf)==1))
Note that there is nothing special of using 20:.1:30, you basically have 101 bins each with probability given by pmf
I have various plots (with hold on) as show in the following figure:
I would like to know how to find equations of these six curves in Matlab. Thanks.
I found interactive fitting tool in Matlab simple and helpful, though somewhat limited in scope:
The graph above seems to be linear interpolation. Given vectors X and Y of data, where X contains the arguments and Y the function points, you could do
f = interp1(X, Y, x)
to get the linearly interpolated value f(x). For example if the data is
X = [0 1 2 3 4 5];
Y = [0 1 4 9 16 25];
then
y = interp1(X, Y, 1.5)
should give you a very rough approximation to 1.5^2. interp1 will match the graph exactly, but you might be interested in fancier curve-fitting operations, like spline approximations etc.
Does rxns stand for reactions? In that case, your curves are most likely exponential. An exponential function has the form: y = a*exp(b * x) . In your case, y is the width of mixing zone, and x is the time in years. Now, all you need to do is run exponential regression in Matlab to find the optimal values of parameters a and b, and you'll have your equations.
The advice, though there might be better answer, from me is: try to see the rate of increase in the curve. For example, cubic is more representative than quadratic if the rate of increase seems fast and find the polynomial and compute the deviation error. For irregular curves, you might try spline fitting. I guess there is also a toolbox in matlab for spline fitting.
There is a way to extract information with the current figure handle (gcf) from you graph.
For example, you can get the series that were plotted in a graph:
% Some figure is created and data are plotted on it
figure;
hold on;
A = [ 1 2 3 4 5 7] % Dummy data
B = A.*A % Some other dummy data
plot(A,B);
plot(A.*3,B-1);
% Those three lines of code will get you series that were plotted on your graph
lh=findall(gcf,'type','line'); % Extract the plotted line from the figure handle
xp=get(lh,'xdata'); % Extract the Xs
yp=get(lh,'ydata'); % Extract the Ys
There must be other informations that you can get from the "findall(gcf,...)" methods.