[R] ggplot with arrows

Rui Barradas
Fri, 01 Aug 2025 15:24:54 -0000

On 8/1/2025 4:15 PM, Rui Barradas wrote:
> On 8/1/2025 3:43 PM, Ebert,Timothy Aaron wrote:
>> I would save the graph as a PowerPoint object and then edit it in
>> PowerPoint.
>> library(ggplot2)
>> library(grid)
>> library(officer)
>> library(rvg)
>> x <- seq(-5, 5, length.out = 100)
>> y <- x^2
>> data <- data.frame(x, y)
>> plot <- ggplot(data, aes(x, y)) +
>> ?? geom_path(color = "blue", linewidth = 1.25) +
>> ?? geom_segment(
>> ???? aes(x = x[1], y = y[1], xend = x[100], yend = y[100]),
>> ???? arrow = arrow(angle = 20, type = "closed", ends =
"both", length
>> = unit(0.2, "inches")),
>> ???? color = "red"
>> ?? ) +
>> ?? theme_linedraw()
>> doc <- read_pptx()
>> doc <- add_slide(doc, layout = "Title and Content", master
= "Office
>> Theme")
>> doc <- ph_with(doc, dml(ggobj = plot), location =
ph_location_fullsize())
>> print(doc, target = "quadratic_with_arrows.pptx")
>>
>> If I remember I think you have to ungroup it in PowerPoint and then
>> all elements become editable. The general approach can be done with
>> other file formats/programs, not just PowerPoint.
>> Tim
>>
>> -----Original Message-----
>> From: R-help <r-help-bounces at r-project.org> On Behalf Of
Thomas Subia
>> via R-help
>> Sent: Friday, August 1, 2025 10:31 AM
>> To: r-help at r-project.org
>> Subject: [R] ggplot with arrows
>>
>> [External Email]
>>
>> Consider:
>>
>> x <- seq(-5,5,length.out = 100)
>> y <- x^2
>> data <- data.frame(x,y)
>> library(ggplot2)
>> ggplot(data,aes(x,y))+
>> ?? stat_function(
>> ???? fun = function(x) x^2,
>> ???? color = "blue", linewidth = 1.25
>> ?? ) +
>> ?? theme_linedraw()
>> I'd like to add an arrow to the ends of curve to illustrate the
curve
>> continues indefinitely in that direction, ChatGPT suggests using
>> geom_segment or geom_link but there has an easier way to do this.
>>
>> Any suggestions would be appreciated.
>>
>>
>> ???????? [[alternative HTML version deleted]]
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide https://www.r-project.org/posting-
>> guide.html
>> and provide commented, minimal, self-contained, reproducible code.
>>
>> ______________________________________________
>> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
>> https://stat.ethz.ch/mailman/listinfo/r-help
>> PLEASE do read the posting guide https://www.R-project.org/posting-
>> guide.html
>> and provide commented, minimal, self-contained, reproducible code.
> Hello,
>
> First of all, according to the documentation ?stat_function, section
> Arguments,
>
>
> data
> Ignored by stat_function(), do not use.
>
>
> As for the arrows, first get the equations of the lines tangent to the
> end points of the parabola,
>
> y = -10*x - 25
> y = 10*x - 25
>
> then compute segments' end points and plot.
>
>
> f <- function(x, b = -25, m) m*x + b
> arrow_data <- data.frame(
>  ? id = c("n", "p"),
>  ? x = c(-5, 5),
>  ? y = f(c(-5, 5), m = c(-10, 10)),
>  ? xend = c(-6, 6),
>  ? yend = f(c(-6, 6), m = c(-10, 10))
> )
>
> ggplot() +
>  ? stat_function(
>  ??? fun = function(x) x^2,
>  ??? color = "blue", linewidth = 1.25,
>  ??? xlim = c(-5, 5)
>  ? ) +
>  ? geom_segment(
>  ??? data = arrow_data,
>  ??? mapping = aes(x = x, y = y, xend = xend, yend = yend, group = id),
>  ??? arrow = arrow(length = unit(0.5, "cm")),
>  ??? linewidth = 1.25,
>  ??? linetype = "dashed",
>  ??? inherit.aes = FALSE
>  ? ) +
>  ? theme_linedraw()
>
>
>
> Remove linetype and add color if you want.
>
> Hope this helps,
>
> Rui Barradas
>
> ______________________________________________
> R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see
> https://stat.ethz.ch/mailman/listinfo/r-help
> PLEASE do read the posting guide https://www.R-project.org/posting-
> guide.html
> and provide commented, minimal, self-contained, reproducible code.
Hello,

Sorry, my previous code is a bit messy.

You don't need to group, so I removed 'id' from the arrow_data.
It's better to define the arrows' end points x coordinates as variables,
it makes it easier to change the plot at will.

And the function is now defined with the intercept as last argument.

f <- function(x, m, b = -25) m*x + b

# here plot with linetype = "dashed"
x0 <- c(-5, 5)
x1 <- c(-6, 6)
arrow_data <- data.frame(
   x = x0,
   y = f(x = x0, m = c(-10, 10)),
   xend = x1,
   yend = f(x = x1, m = c(-10, 10))
)

ggplot() +
   stat_function(
     fun = function(x) x^2,
     color = "blue", linewidth = 1.25,
     xlim = c(-5, 5)
   ) +
   geom_segment(
     data = arrow_data,
     mapping = aes(x = x, y = y, xend = xend, yend = yend),
     arrow = arrow(length = unit(0.5, "cm")),
     linewidth = 1.25,
     linetype = "dashed",
     inherit.aes = FALSE
   ) +
   theme_linedraw()


#---

# here the line type is the default solid, so
# start the arrows a bit away from the parabola, 0.1 away.
x0 <- c(-5.1, 5.1)
x1 <- c(-6, 6)
arrow_data <- data.frame(
   x = x0,
   y = f(x = x0, m = c(-10, 10)),
   xend = x1,
   yend = f(x = x1, m = c(-10, 10))
)

ggplot() +
   stat_function(
     fun = function(x) x^2,
     color = "blue", linewidth = 1.25,
     xlim = c(-5, 5)
   ) +
   geom_segment(
     data = arrow_data,
     mapping = aes(x = x, y = y, xend = xend, yend = yend),
     arrow = arrow(length = unit(0.5, "cm")),
     linewidth = 1.25,
     inherit.aes = FALSE
   ) +
   theme_linedraw()


Hope this helps,

Rui Barradas