'How to accurately add a intersection line on a plot in R?

I am trying to add a right angled intersection line to a ggplot.

For example, in the code\plot below, I draw a dashed line at some given threshold x-value. Ideally, I want this line to intersect the the curve and go to the corresponding spot on the y-axis. As you can see, at the moment I just extend it to y=1.

I was wondering if there was a way to find the corresponding y-value, if given only the x-value for any type of curve?

library(ggplot2)

# create data
df <- data.frame(
  x = seq(0,1, by = 0.1),
  y =  pexp(seq(0, 1, by = 0.1), rate = 4)
)

# set treshold
threshold <- 0.5

# plot
ggplot(df, aes(x, y)) +
  geom_line() +
  geom_segment(aes(x = threshold, xend = threshold, y = -Inf,  yend = 1), linetype = 2)+
  geom_segment(aes(x = -Inf, xend = threshold, y = 1, yend = 1),  linetype = 2) +
  theme_bw()

plot with intersection line

r


Solution 1:[1]

Do you mean this?

df2 <- with(approx(df$x, df$y, xout = threshold),
            data.frame(x1 = c(-Inf, x, x), y1 = c(y, y, -Inf)))
ggplot(df, aes(x, y)) +
  geom_line() +
  geom_line(aes(x = x1, y = y1), linetype = 2, data = df2) +
  theme_bw()

exponential curve with intersecting lines

Solution 2:[2]

You could predict a loess regression to find the desired y value.

(y1 <- predict(loess(y ~ x, df), newdata=list(x=threshold)))
#         x 
# 0.8657561     

plot(y ~ x, df, type='l', col=4, xaxs='i', yaxs='i')
segments(0, y1, threshold, y1, lty=3, col=2)
segments(threshold, y1, threshold, 0, lty=3, col=2)
## optional:
mtext(round(y1, 2), 2, at=y1, col=2)
mtext(threshold, 1, at=threshold, col=2)

enter image description here

When you have a "real" curve, i.e. the function is known:

set.seed(42)
cf <- runif(5)
f <- \(x) cf[1] + cf[2]*x + cf[3]*x^2 + cf[4]*x^3 + cf[5]*x^4
y2 <- f(threshold)

curve(f)
segments(par()$usr[1], y2, threshold, y2, lty=2, col=2)  ## `par` gives margins
segments(threshold, y2, threshold, 0, lty=2, col=2)

enter image description here

Using the ggplot2 package

library(ggplot2)
ggplot(df, aes(x, y)) +
  geom_line() +
  geom_segment(aes(x=threshold, xend=threshold, y=-Inf,  yend=y1), linetype=2) +
  geom_segment(aes(x=-Inf, xend=threshold, y=y1, yend=y1),  linetype=2) +
  theme_bw()

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 r2evans
Solution 2