Drawing a Tangent to the Plot and Finding the X-Intercept Using R

Drawing a Tangent to the Plot and Finding the X-Intercept using R

Here's an option using derivatives of a fitted spline function (smooth.spline - you may need to adjust the parameter spar to your case):

x <- seq(0,40)
y <- dnorm(seq(0,40), mean=25, sd=5)
plot(x, y)
spl <- smooth.spline(y ~ x)
lines(spl, col=2)

newx <- 20
pred0 <- predict(spl, x=newx, deriv=0)
pred1 <- predict(spl, x=newx, deriv=1)

yint <- pred0$y - (pred1$y*newx)
xint <- -yint/pred1$y
xint

The results visually:

plot(x, y)
abline(h=0, col=8)
lines(spl, col=2) # spline
points(pred0, col=2, pch=19) # point to predict tangent
lines(x, yint + pred1$y*x, col=3) # tangent (1st deriv. of spline at newx)
points(xint, 0, col=3, pch=19) # x intercept

Sample Image

Update

Here is an example using your dataset (df):

# fit smooth spline
plot(y ~ x, df)
spl <- smooth.spline(df$x, df$y, spar=0.3)
newx <- seq(min(df$x), max(df$x), 0.1)
pred <- predict(spl, x=newx, deriv=0)
lines(pred, col=2)

# solve for tangent at a given x
newx <- 25
pred0 <- predict(spl, x=newx, deriv=0)
pred1 <- predict(spl, x=newx, deriv=1)
yint <- pred0$y - (pred1$y*newx)
xint <- -yint/pred1$y
xint

# plot results
plot(y ~ x, df)
abline(h=0, col=8)
lines(spl, col=2) # spline
points(pred0, col=2, pch=19) # point to predict tangent
lines(x, yint + pred1$y*x, col=3) # tangent (1st deriv. of spline at newx)
points(xint, 0, col=3, pch=19) # x intercept

Sample Image

I'm not sure how much noise is in your data, but by using a smaller spar setting in smooth.spline, you can increase the detail of the fitted function.

How can I plot a tangent line in R?

The key here is first to calculate the slope and the intercept correctly, and then use geom_ribbon and geom_abline. So if you wish to calculate the slope in 0.1, I suggest you calculate the ratio between the y increment and x increment in the interval x = 0.9 and x = 0.11, that is:

xincrement <- 0.02
yincrement <- prc_yld[10, 2] - prc_yld[8, 2]
slope <- yincrement/xincrement

Then, the intercept is:

intercept <- 100-slope*0.1

With these values, we can calculate the yvalues of the tangent line:

yvalues <- slope*prc_yld$prc_yld + intercept

Now, let's combine all together:

 prc_yld <- as.data.frame(cbind(prc_yld, yvalues))

Now, the plot:

ggplot(prc_yld, aes(x=prc_yld, y = price)) + 
geom_ribbon(data = prc_yld, aes(x = prc_yld, ymax = price, ymin = yvalues), fill = "green") +
geom_line(color = "red", size = 1) +
labs(title ="Price/YTM Relationship",x="Yield", y= "Value") +
geom_abline(slope = slope, intercept = intercept, color = "blue", size = 1)

How to totally remove x-axis (and y-axis) from the plot and also draw tangent lines at certain points using Python or R-programming?

Using Python,

import numpy as np
import matplotlib.pyplot as plt

tau = np.arange(-5, 5, 0.01)
a = 0.4

sigma = a*tau
x = 1/a*np.cosh(sigma)
y = 1/a*np.sinh(sigma)

fig, ax = plt.subplots()
ax.plot(x, y, c='black')

# approximate the curve by a cubic
dxds = np.poly1d(np.polyfit(sigma, x, 3)).deriv()
dyds = np.poly1d(np.polyfit(sigma, y, 3)).deriv()

xs, ys, dxs, dys = [], [], [], []
for s in np.linspace(-1, 1, 5):
# evaluate the derivative at s
dx = np.polyval(dxds, s)
dy = np.polyval(dyds, s)

# record the x, y location and dx, dy tangent vector associated with s
xi = 1/a*np.cosh(s)
yi = 1/a*np.sinh(s)
xs.append(xi)
ys.append(yi)
dxs.append(dx)
dys.append(dy)
if s == 0:
ax.text(xi-0.75, yi+1.5, '$u$', transform=ax.transData)
ax.annotate('$a^{-1}$',
xy=(xi, yi), xycoords='data',
xytext=(25, -5), textcoords='offset points',
verticalalignment='top', horizontalalignment='left',
arrowprops=dict(arrowstyle='-', shrinkB=7))

ax.quiver(xs, ys, dxs, dys, scale=1.8, color='black', scale_units='xy', angles='xy',
width=0.01)
ax.plot(xs, ys, 'ko')

# http://stackoverflow.com/a/13430772/190597 (lucasg)
ax.set_xlim(-0.1, x.max())
left, right = ax.get_xlim()
low, high = ax.get_ylim()
ax.arrow(0, 0, right, 0, length_includes_head=True, head_width=0.15 )
ax.arrow(0, low, 0, high-low, length_includes_head=True, head_width=0.15 )
ax.text(0.03, 1, '$t$', transform=ax.transAxes)
ax.text(1, 0.47, '$x$', transform=ax.transAxes)

plt.axis('off')
ax.set_aspect('equal')
plt.show()

yields

Sample Image

How do you draw a straight line tangent to smoothed curve in R?

I tried running your data and d wasn't defined in the code so was not able to reproduce your example.

Using geom_abline you can add a line with the own intercept and slope if you know these dimensions.

ggplot(aes(x = wt, y = mpg), data = mtcars) +
geom_point()+
labs(x = 'wt', y = 'mpg') +
geom_abline(intercept = 10, slope = 6)+
geom_smooth(method = 'loess', col='black', level=0.5, alpha=0.1)

This gave something like this. line with geom_smooth.

I'm not a complete expert but I hope this helps in some way shape or form.

How to add the x intercept from geom_vline in density plot as a label?

One approach is to pre-calc the means and use those to feed geom_vline and geom_text:

library(dplyr)
iris_means <- iris %>%
group_by(Species) %>%
summarize(mean = mean(Sepal.Length))

ggplot(iris, aes(Sepal.Length)) +
geom_density() +
geom_vline(data = iris_means, aes(xintercept = mean)) +
geom_text(data = iris_means, aes(x = mean, label = mean),
y = 0.1, angle = 90, vjust = -0.2) +
facet_wrap(~Species)

Sample Image

Finding x-value for a given y-value

You can use unitroot to find the point where y matches:

x <- seq(0,40)
y <- pnorm(seq(0,40), mean=25, sd=5)
spl <- smooth.spline(y ~ x)

newy <- 0.85
newx <- uniroot(function(x) predict(spl, x, deriv = 0)$y - newy,
interval = c(0, 40))$root

plot(x, y)
lines(spl, col=2)
points(newx, newy, col=3, pch=19)

Sample Image

Concerning the algorithm, we get from ?uniroot:

uniroot() uses Fortran subroutine ‘"zeroin"’ (from Netlib) based on
algorithms given in the reference below. They assume a continuous
function (which then is known to have at least one root in the
interval).

[...]

Based on ‘zeroin.c’ in http://www.netlib.org/c/brent.shar.

[...]

Brent, R. (1973) Algorithms for Minimization without Derivatives.
Englewood Cliffs, NJ: Prentice-Hall.

See also https://en.wikipedia.org/wiki/Brent%27s_method.



Related Topics



Leave a reply



Submit