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()
CodePudding user response:
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()
CodePudding user response:
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)
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)
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()