I am doing some caclulations with extreme velocities and the only way to solve my system equations is to do it graphically. Once I have plotted my curve, I would like to develop a function that enter an x-value and the function itself plots a line from this x-value up to the corresponding point of the curve and from this point, another line over y-value. Like this I would get my y-value that would be the solution of my system equations.
Here is my code. The function Vr_Vmed is the expression of my final equation. In fact, n=4 and Tr=50 and x is the variable.
par(font=10,font.axis=10,font.lab=10,font.main=11,font.sub=10)
curve(Vr_Vmed(x,n,Tr),xlim=c(1,2.5),ylim=c(1,17),
xaxs="i",yaxs="i",xaxt="n",yaxt="n",lwd=2,
xlab="K Weibull",ylab="Vref / Vmed",usr=c(1,2.5,1,17),
main="Vref Estimation")
axis(1,at=c(seq(1,2.5,0.1)),xaxp=c(1,2.5,1))
axis(2,at=c(seq(1,17,1)))
If you just want to add lines to your plot,
you can use lines or segments.
f <- function(x) {
y <- Vr_Vmed(x,n,Tr)
lines(c(x,x,0),c(0,y,y))
}
f(2)
(But that does not "solve" anything: your Vr_med function
aparently does all the work.)
Related
There are a number of questions in this forum on locating intersections between a fitted model and some raw data. However, in my case, I am in an early stage project where I am still evaluating data.
To begin with, I have created a data frame that contains a ratio value whose ideal value should be 1.0. I have plotted the data frame and also used abline() function to plot a horizontal line at y=1.0. This horizontal line and the plot of ratios intersect at some point.
plot(a$TIME.STAMP, a$PROCESS.RATIO,
xlab='Time (5s)',
ylab='Process ratio',
col='darkolivegreen',
type='l')
abline(h=1.0,col='red')
My aim is to locate the intersection point, say x and draw two vertical lines at x±k, as abline(v=x-k) and abline(v=x+k) where, k is certain band of tolerance.
Applying a grid on the plot is not really an option because this plot will be a part of a multi-panel plot. And, because ratio data is very tightly laid out, the plot will not be too readable. Finally, the x±k will be quite valuable in my discussions with the domain experts.
Can you please guide me how to achieve this?
Here are two solutions. The first one uses locator() and will be useful if you do not have too many charts to produce:
x <- 1:5
y <- log(1:5)
df1 <-data.frame(x= 1:5,y=log(1:5))
k <-0.5
plot(df1,type="o",lwd=2)
abline(h=1, col="red")
locator()
By clicking on the intersection (and stopping the locator top left of the chart), you will get the intersection:
> locator()
$x
[1] 2.765327
$y
[1] 1.002495
You would then add abline(v=2.765327).
If you need a more programmable way of finding the intersection, we will have to estimate the function of your data. Unfortunately, you haven’t provided us with PROCESS.RATIO, so we can only guess what your data looks like. Hopefully, the data is smooth. Here’s a solution that should work with nonlinear data. As you can see in the previous chart, all R does is draw a line between the dots. So, we have to fit a curve in there. Here I’m fitting the data with a polynomial of order 2. If your data is less linear, you can try increasing the order (2 here). If your data is linear, use a simple lm.
fit <-lm(y~poly(x,2))
newx <-data.frame(x=seq(0,5,0.01))
fitline = predict(fit, newdata=newx)
est <-data.frame(newx,fitline)
plot(df1,type="o",lwd=2)
abline(h=1, col="red")
lines(est, col="blue",lwd=2)
Using this fitted curve, we can then find the closest point to y=1. Once we have that point, we can draw vertical lines at the intersection and at +/-k.
cross <-est[which.min(abs(1-est$fitline)),] #find closest to 1
plot(df1,type="o",lwd=2)
abline(h=1)
abline(v=cross[1], col="green")
abline(v=cross[1]-k, col="purple")
abline(v=cross[1]+k, col="purple")
Im writing a basic script to find the min distance between f(x):=log(x)-x and the origin. I would like to be able to plot the point closest to the origin over the top of a plot of f(x), but i can not figure out how to plot a single point.
Here is what i have written. Any ideas?
f(x):=log(x)-x;
d(x):=sqrt(x^2+f(x)^2)$
find_root(diff(d(x),x),x,0.01,5)$
a:%;
f(a);
print("min distance from f(x) to (0,0)")$
d(a);
print("passes second derivative test if next value greater than zero")$
g(x):=''(diff(d(x),x,2))$
g(a);
wxplot2d([f(x)], [x,.01,5], [y,-6,0])$
Use the discrete option as a second curve, and then use points in the style option.
Replacing your last line with
wxplot2d([f(x), [discrete, [a], [f(a)]]], [x,.01,5], [y,-6,0],
[style, lines, points],
[legend, "log(x)-x", "closest point to origin"],
[point_type, circle],
[gnuplot_preamble, "set key bottom"])$
gives you this:
I am stuck in simple problem. I have a scatter plot.
I am plotted confidence lines around it using my a custom formula. Now, i just want only the names outside the cutoff lines to be displayed nothing inside. But, I can't figure out how to subset my data on the based of the line co-ordinates.
The line is plotted using the lines function which is a vector of 128 x and y values. Now, how do I subset my data (x,y points) based on these 2 values. I can apply a static limit of a single number of sub-setting data like 1,2 or 3 but how to use a vector to subset data, got me stuck.
For an reproducible example, consider :
df=data.frame(x=seq(2,16,by=2),y=seq(2,16,by=2),lab=paste("label",seq(2,16,by=2),sep=''))
plot(df[,1],df[,2])
# adding lines
lines(seq(1,15),seq(15,1),lwd=1, lty=2)
# adding labels
text(df[,1],df[,2],labels=df[,3],pos=3,col="red",cex=0.75)
Now, I need just the labels, which are outside or intersecting the line.
What I was trying to subset my dataframe with the values used for the lines, but I cant make it right.
Now, static sub-setting can be done for single values like
df[which(df[,1]>8 & df[,2]>8),] but how to do it for whole list.
I also tried sapply, to cycle over all the values of x and y used for lines on the df iteratively, but most values become +ve for a limit but false for other values.
Thanks
I will speak about your initial volcano-type-graph problem and not the made up one because they are totally different.
So I really thought this a lot and I believe I reached a solid conclusion. There are two options:
1. You know the equations of the lines, which would be really easy to work with.
2. You do not know the equation of the lines which means we need to work with an approximation.
Some geometry:
The function shows the equation of a line. For a given pair of coordinates (x, y), if y > the right hand side of the equation when you pass x in, then the point is above the line else below the line. The same concept stands if you have a curve (as in your case).
If you have the equations then it is easy to do the above in my code below and you are set. If not you need to make an approximation to the curve. To do that you will need the following code:
df=data.frame(x=seq(2,16,by=2),y=seq(2,16,by=2),lab=paste("label",seq(2,16,by=2),sep=''))
make_vector <- function(df) {
lab <- vector()
for (i in 1:nrow(df)) {
this_row <- df[i,] #this will contain the three elements per row
if ( (this_row[1] < max(line1x) & this_row[2] > max(line1y) & this_row[2] < a + b*this_row[1])
|
(this_row[1] > min(line2x) & this_row[2] > max(line2y) & this_row[2] > a + b*this_row[1]) ) {
lab[i] <- this_row[3]
} else {
lab[i] <- <NA>
}
}
return(lab)
}
#this_row[1] = your x
#this_row[2] = your y
#this_row[3] = your label
df$labels <- make_vector(df)
plot(df[,1],df[,2])
# adding lines
lines(seq(1,15),seq(15,1),lwd=1, lty=2)
# adding labels
text(df[,1],df[,2],labels=df[,4],pos=3,col="red",cex=0.75)
The important bit is the function. Imagine that you have df as you created it with x,y and labs. You also will have a vector with the x,y coordinates for line1 and x,y coordinates for line2.
Let's see the condition of line1 only (the same exists for line 2 which is implemented on the code above):
this_row[1] < max(line1x) & this_row[2] > max(line1y) & this_row[2] < a + b*this_row[1]
#translates to:
#this_row[1] < max(line1x) = your x needs to be less than the max x (vertical line in graph below
#this_row[2] > max(line1y) = your y needs to be greater than the max y (horizontal line in graph below
#this_row[2] < a + b*this_row[1] = your y needs to be less than the right hand side of the equation (to have a point above i.e. left of the line)
#check below what the line is
This will make something like the below graph (this is a bit horrible and also magnified but it is just a reference. Visualize it approximating your lines):
The above code would pick all the points in the area above the triangle and within the y=1 and x=1 lines.
Finally the equation:
Having 2 points' coordinates you can figure out a line's equation solving a system of two equations and 2 parameters a and b. (y = a +bx by replacing y,x for each point)
The 2 points to pick are the two points closest to the tangent of the first line (line1). Chose those arbitrarily according to your data. The closest to the tangent the better. Just plot the spots and eyeball.
Having done all the above you have your points with your labels (approximately at least).
And that is the only thing you can do!
Long talk but hope it helps.
P.S. I haven't tested the code because I have no data.
I plotted an expression curve, i.e.curve(-log((1-x)/0.9999)/x,ylim=c(0,4)).
However, I want to see the reverse relationship, i.e. y changes over x instead of x changes over y. Are there any R function can plot it automatically? Or a function that can solve the equation?
There are two obvious choices:
(i) derive the inverse function algebraically (trivial in this case),
That is, take y=-log((1-x)/0.9999) and make x the subject of the equation (which would require straightforward algebraic manipulation suitable for a question on math.SE if it's not obvious how to proceed)...
... and then use curve on the result of that, or
(ii) use plot rather than curve to plot a set of (x,y) pairs (set type="l" to get a curve), and simply interchange which is x and which is y in the call to plot.
I would like to find the points of intersection between an ellipse and a line
If using the example (ignoring a few un-needed arguments) from the dataEllipse function from the car package i.e.
x <- dataEllipse(Prestige$income, Prestige$education, levels=0.95, lty=2)
and say you have the horizontal line
abline(14,0)
how do you find the two points of intersection between the line and the ellipse
I know you can get the data that makes the ellipse from just looking at x, however I would like to get the exact points of intersection.
The equation of an ellipse is given by:
x^2/a+y^2/b=1, and the equation of a line by cx+d=y (where a,b,c,d coefficients).
You can substitute y in the ellipse equation. Then the goal is to find the solution of f(x)=0. You can use some method like bisection to solve such a problem.
Check this out:
http://www.math.wichita.edu/~cma/stat774/ch2.pdf
I bet there's a curve-fitting method that can get the foci and axis lengths of your ellipse from the set of x-y coords, but it looks tough: http://www.site.uottawa.ca/~mstoj075/Publications_files/EllipseFit.pdf . You might get a "good enough" answer by using splinefun on your set of x-y coordinate data and following the answers in The intersection point between a spline and a line