Hi all,
I produced a graph using geom_smooth() function and I want to identify the point that there is a change in trend from upwards to downwards. Does someone has an idea how this happens?
Many thanks in advance.
Panos
I don't think geom_smooth()
can give you that directly. Under the hood, geom_smooth()
is actually using a type of loess()
smoothing, so you could use that directly:
library(tidyverse)
dat <- tibble(x = 1:100,
y = ifelse(x<50, 2*x, -2*x + 200) + rnorm(100, sd = 10))
ggplot(dat, aes(x, y)) +
geom_point() +
geom_smooth()
#> `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
mod <- loess(y ~ x, data = dat)
predict(mod, 1:100) |>
diff() |>
sign() |>
diff()
#> [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> [26] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 -2 0 0
#> [51] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#> [76] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Created on 2023-06-19 with reprex v2.0.2
But for more advanced methods, I suggest you look up "R time series changepoint detection", there is a lot of resources that exist!
Thanks Alex! However still I cannot find the point where the trend is changing
Of the steps to follow that Alex laid out, which one trips you up ?
What Alex suggested leads to a graph with a smooth_line. However I want (say in his graph) to see the coordinates where the smooth_line changes inclination (from upwards to dowanwards)
Alex's example went as far as to detect the difference in sign as x is traversed. we can find the location by adding a little more
predict(mod, 1:100) |>
diff() |>
sign() |>
diff() |> which.min()
this gives me '49'
the 49th position of 1:100 is itself '49'
Here's a further example adapted from Alex, where the correspondence with x is less obvious, but still retreivable.
library(tidyverse)
dat <- tibble(x = 25:60,
y = ifelse(x<50, 2*x, -2*x + 200) + rnorm(36, sd = 10))
ggplot(dat, aes(x, y)) +
geom_point() +
geom_smooth()
#> `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
mod <- loess(y ~ x, data = dat)
predict(mod, 25:60) |>
diff() |>
sign() |>
diff() |> which.min()
#24
(25:60)[24]
# x=48
in this example x is from 25:60 , the point of sign change is the 24th entry of x, which is the value x=48
I suppose your question may be simply how to annotate a chart ?
+ geom_vline(xintercept = 48)
will add a vertical line at the x value you choose
My question includes how to annotate the chart but I don't want all points to be shown. Moreover, how do you know that xintercept=48? It makes sense after the piece of work that you added.
Many thanks for your help!
This topic was automatically closed 42 days after the last reply. New replies are no longer allowed.
If you have a query related to it or one of the replies, start a new topic and refer back with a link.