Octave smooth curve graph - matlab

I want to draw a smooth curve fit graph in Octave on my data instead of sharp line just like scatter with smooth line in Excel.
My data as as follows:
x = [1, 2 , 3];
y = [53, 48, 31];
y1 = [89, 51, 49];
When i do a normal plot it gives linear graph with sharp edges on a point. I want smooth graph. How can i plot that in Octave. Thank you

Well, you only have 3 data points, so of course your graph is not going to be "smooth". Get (much) more data points, and you will have a "smooth" graph, provided your data is "smooth".
You can also fit a "smooth" curve to your data, but that's a different question entirely, plus you will also need more data points for a meaningful fit.

Very old, but might still be useful. Do e.g.
x = [1, 2 , 3];
y = [53, 48, 31];
y1 = [89, 51, 49];
xspline = linspace(min(x),max(x),100);
yspline = interp1(x,y,xspline,"pchip");
yspline1 = interp1(x,y1,xspline,"pchip");
plot(xspline,yspline,xspline,yspline1);
You can find different interpolation "smoothing" methods by entering
help interp1
in the example above
"pchip"
Piecewise cubic Hermite interpolating
polynomial--shape-preserving interpolation with smooth first
derivative.
is used.

Related

Matlab Graphing in 4D with Symbolic Variables

I have the following equations:
FindBurrow = .3*log(x+2)-.2
DistEffect= normpdf(y,0,6) + 0.92
VegEffect = -.006*z+1
Detection = FindBurrow*DistEffect*VegEffect
I would like to visualize the Detection function as part of a 4-D visualization. The fourth dimension would be color to represent Detection. I see that it is possible to do this if I have matrices with real x,y,z values but I currently don't.
I have tried to convert my symbolic x,y,z values to real 100 by 100 matrices using the following but it doesn't seem to work properly.
%% Conversion to "Real" Numbers
syms f(x,y,z)
f(x,y,z) = Detection;
[x,y] = ndgrid(linspace(1/10,50), linspace(1/10, 50))
z] = ndgrid(linspace(1/10,50), linspace(1/10, 50))
g = matlabFunction(Detection);
DetKernel = real(g(x,y,z))
%% Graphing the IPM
figure
surf(x,y,z,DetKernel) % surface map
clear title xlabel ylabel %Clears old runs index
xlabel ('Burrow Size') %x-axis label
ylabel('Distance From Line') %y-axis label
zlabel('Vegetation Effect') %z-axis label
cb = colorbar;
cb.Label.String = 'Probability of Detection';
I suspect this is due to a lack of knowledge of how to define the x,y,z values to make them act like grid points that Matlab will then use to make a surface or mesh. The graphing part seems to work okay, just doesn't make the shape I would expect based on experimental plotting of the XY, YZ, Z*X equations.
In short I have two questions: 1. Can I graph 4D using symbolic variables? 2. If not, how do I convert to real numbers without messing up my data?
For reference, x will be between 0 and 55, y will be between 0 and 25 and z will be between 0 and 160.

MATLAB Histogram Problems

I need to calculate the probability density of the function 1/2-x where x is a randomly generated number between 0 and 1.
My code looks like this:
n=10^6;
b=10^2;
x=(1./(2-(rand(1,n))));
a=histfit(x,b,'kernel'); % Requires Statistics and Machine Learning Toolbox
xlim([0.5 1.0])
And I get a decent graph that looks like this:
As it may be apparent, there are a couple of problems with this:
MATLAB draws a fit that differs from my histogram, because it counts in the empty space outside the [0.5 1] range of the function as well. This results in a distorted fit towards the edges. (The reason you don't see said empty space is because I entered an xlim there)
I don't know how I could divide every value in the Y-axis by 10^6, which would give me my probability density.
Thanks in advance.
To solve both of your problems, I suggest using hist (Note if you have a version above 2010b, you should use histogram instead) instead of histfit to first get the values of your histogram and then doing a regression and plotting them:
n=10^6;
b=10^2;
x=(1./(2-(rand(1,n))));
[counts,centers]=hist(x,b);
density = counts./trapz(centers, counts);
%// Thanks to #Arpi for this correction
polyFitting = polyfit(centers,density,3)
polyPlot = polyval(polyFitting,centers)
figure
bar(centers,density)
hold on
plot(centers,polyPlot,'r','LineWidth',3)
You can also up the resolution by adjusting b, which is set to 100 currently. Also try different regressions to see which one you prefer.
1. Better result can be obtained by using ksdensity and specifying the support of the distribution.
2. By using hist you have access to the counts and centers, thus the normalization to get density is straightforward.
Code to demonstrate the suggestions:
rng(125)
n=10^6;
b=10^2;
x=(1./(2-(rand(1,n))));
subplot(1,2,1)
a = histfit(x,b,'kernel');
title('Original')
xlim([0.5 1.0])
[f,c] = hist(x,b);
% normalization to get density
f = f/trapz(c,f);
% kernel density
pts = linspace(0.5, 1, 100);
[fk,xk] = ksdensity(x, pts, 'Support', [0.5, 1]);
subplot(1,2,2)
bar(c,f)
hold on
plot(xk,fk, 'red', 'LineWidth', 2)
title('Improved')
xlim([0.5 1.0])
Comparing the results:
EDIT: If you do not like the endings:
pts = linspace(0.5, 1, 500);
[fk,xk] = ksdensity(x, pts, 'Support', [0.5, 1]);
bar(c,f)
hold on
plot(xk(2:end-1),fk(2:end-1), 'red', 'LineWidth', 2)
title('Improved_2')
xlim([0.5 1.0])

Matlab partial area under the curve

I want to plot the area above and below a particular value in x axis.
The problem i am facing is with discrete values. The code below for instance has an explicit X=10 so i have written it in such a way that i can find the index and calculate the values above and below that particular value but if i want to find the area under the curve above and below 4 this program will now work.
Though in the plot matlab does a spline fitting(or some sort of fitting for connecting discrete values) there is a value for y corresponding to x=4 that matlab computes i cant seem to store or access it.
%Example for Area under the curve and partial area under the curve using Trapezoidal rule of integration
clc;
close all;
clear all;
x=[0,5,10,15,20];% domain
y=[0,25,50,25,0];% Values
LP=log2(y);
plot(x,y);
full = trapz(x,y);% plot of the total area
I=find(x==10);% in our case will be the distance value up to which we want
half = trapz(x(1:I),y(1:I));%Plot of the partial area
How can we find the area under the curve for a value of ie x = 2 or 3 or 4 or 6 or 7 or ...
This is an elaboration of patrik's comment, "first interpolate and then integrate".
For the purpose of this answer I'll assume that the area in question is the area that can be seen in the plot, and since plot connects points by straight lines I assume that linear interpolation is adequate. Moreover, since the trapezoidal rule itself is based on linear interpolation, we only need interpolated values at the beginning and end of the interval.
Starting from the given points
x = [0, 5, 10, 15, 20];
y = [0, 25, 50, 25, 0];
and the integration interval limits, say
xa = 4;
xb = 20;
we first select the data points within the limits
ind = (x > xa) & (x < xb);
xw = x(ind);
yw = y(ind);
and then complete them by interpolation values at the edges:
ya = interp1(x, y, xa);
yb = interp1(x, y, xb);
xw = [xa, xw, xb];
yw = [ya, yw, yb];
Now we can simply apply trapezoidal integration:
area = trapz(xw, yw);
I think that you either need more samples, or to interpolate the data. Another alternative is to use a function handle. Then you need to know the function though. Example using linear interpolation follows.
x0 = [0;5;10;15;20];
y0 = [0,25,50,25,0];
x1 = 0:20;
y1 = interp1(x0,y0,x1,'linear');
xMax = 4;
partInt = trapz(x1(x1<=xMax),y1(x1<=xMax));
Some other kind of interpolation may be suitable, but that is hard to say without more information. Also, this interpolates from the beginning to x. However, I guess figuring out how to change the limits should be easy from here. This solution is different than the former, since it is less depending on the pyramid shape of the data. So to say, it is more general.

How to make a graph tangent to tops of another graph?

I've got a graph: the velocity as a function of the rpm of a car. The actual graph consists of four subgraphs (one for each of the 4 gears of the car). I conjoined those sub-graphs with a for loop and some if statements. This resulting graph is shown below.
I need to add a graph which is tangent to all the tops of the graphs, like the red line. The final result would look like this:
(It's now still without the red line, obviously...)
These are the coordinates where the tangent line would touch the graph: (17, 5130.36), (28, 3117.98), (39, 2239.37), (51, 1714.72).
Since you already know the tangent points,
x = [17 28 39 51];
y = [5130.36 3117.98 2239.37 1714.72];
plot(x, y, 'b.')
the solution is a simple interpolation
xs = linspace(min(x), max(x), 100);
ys = spline(x, y, xs);
hold on
plot(xs, ys, 'r')
with the result:
I here used Matlab's standard cubic spline interpolation; depending on the properties of your data, other interpolation functions might give better results. In particular, if you knew not only the positions of the tangent points but also the tangent slope, you could use that information to impose constraints on a piecewise polynomial interpolation.

MATLAB vectors, angles, plots

I apologize for the ambiguous title, but I am not entirely sure how to phrase this one. So bear with me.
I have a matrix of data. Each column and row represents a certain vector (column 1 = row 1, column 2 = row 2, etc.), and every cell value is the cosine similarity between the corresponding vectors. So every value in the matrix is a cosine.
There are a couple of things I want to do with this. First, I want to create a figure that shows all of the vectors on it. I know the cosine of the angle between every vector, and I know the magnitude of each vector, but that is the only information I have - is there some algorithm I can implement that will run through all of the various pair-wise angles and display it graphically? That is, I don't know where all the vectors are in relation to each other, and there are too many data points to do this by hand (e.g. if I only had three vectors, and the angles between them all were 45, 12, and 72 degrees it would be trivial). So how do I go about doing this? I don't even have the slightest idea what sort of mathematical function I would need to do this. (I have 83 vectors, so that's thousands of cosine values). So basically this figure (it could be either 2D or multidimensional, and to be honest I would like to do both) would show all of the vectors and how they relate to each other in space (so I could compare both angles and relative magnitudes).
The other thing I would like to do is simpler but I am having a hard time figuring it out. I can convert the cosine values into Cartesian coordinates and display them in a scatter plot. Is there a way to connect each of the points of a scatter plot to (0,0) on the plot?
Finally, in trying to figure out how to do some of the above on my own I have run into some inconsistencies. I calculated the mean angles and Cartesian coordinates for each of the 83 vectors. The math for this is easy, and I have checked and double-checked it. However, when I try to plot it, different plotting methods give me radically different things. So, if I plot the Cartesian coordinates as a scatter plot I get this:
If I plot the mean angles in a compass plot I get this:
And if I use a quiver plot I get something like this (I transformed this a little by shifting the origin up and to the right just so you can see it better):
Am I doing something wrong, or am I misunderstanding the plotting functions I am using? Because these results all seem pretty inconsistent. The mean angles on the compass plot are all <30 degrees or so, but on the quiver plot some seem to exceed 90 degrees, and on the scatter plot they extend above 30 as well. What's going on here?
(Here is my code:)
cosine = load('LSA.txt');
[rows,columns]=size(cosine);
p = cosine.^2;
pp = bsxfun(#minus, 1, p);
sine = sqrt(pp);
tangent = sine./cosine;
Xx = zeros(rows,1);
Yy = zeros(rows,1);
for i = 1:columns
x = cosine(:,i);
y = sine(:,i);
Xx(i,1) = sum(x) * (1/columns);
Yy(i,1) = sum(y) * (1/columns);
end
scatter(Xx,Yy);
Rr = zeros(rows,1);
Uu = zeros(rows,1);
for j = 1:rows
Rr(j,1) = sqrt(Xx(j,1).^2 + Yy(j,1).^2);
Uu(j,1) = atan2(Xx(j,1),Yy(j,2));
end
%COMPASS PLOT
[theta,rho] = pol2cart(Uu,1);
compass(theta,rho);
%QUIVER PLOT
r = 7;
sx = ones(size(cosine))*2; sy = ones(size(cosine))*2;
pu = r * cosine;
pv = r * sine;
h = quiver(sx,sy,pu,pv);
set(gca, 'XLim', [1 10], 'YLim', [1 10]);
You can exactly solve this problem. The dot product calculates the cosine. This means your matrix is actually M=V'*V
This should be solvable through eigenvalues. And you said you also have the length.
Your only problem - as your original matrix the vectors will be 83 dimensional. Not easy to plot in 2 or 3 dimensions. I think you are over simplifying by just using the average angle. There are some techniques called dimensionality reduction - here's a toolbox. I would suggest a sammon projection on 1-cosine (as this would be the distance of points on the unit ball) to calculate the vectors for such a plot.
In the quiver plot, you are plotting all of the data in the cosine and sine matrices. In the other plots, you are only plotting the means. The first two plots appear to match up, so no problem there.
A few other things. I notice that in
Uu(j,1) = atan2(Xx(j,1),Yy(j,2));
Yy(j,2) is not actually defined, so it seems like this code should fail.
Furthermore, you could define Yy and Xx as:
Xx = mean(cosine,2);
Yy = mean(sine,2);
And also get rid of the other for loop:
Rr = sqrt(Xx.^2 + Yy.^2)
Uu = atan2(Xx,Yy)
I still have to think about your first question, but I hope this was helpful.