Search code examples
rvectorplotlyarrows

Plotly: How to set style and color for the arrows using add_annotations?


I want to represent 2D vectors rooted at the origin with plotly in R. Moreover, I want to color the vector based on a categorical variable. The problem is that I can either create the lines color-coded but without the arrow head:


library(plotly)
library(dplyr)

v <- c(1, 1)
b1 <- c(1, 0)
b2 <- c(0, 1)
df <- data.frame(
  x = c(v[1], b1[1], b2[1]),
  y = c(v[2], b1[2], b2[2]),
  is_basis = c(FALSE, TRUE, TRUE)
)
df %>% 
  plot_ly(x = ~x, y = ~y, color = ~is_basis) %>%
  add_segments(xend = ~x, yend = ~y, x = 0, y = 0, colors = c("red","black"))

Or with the arrow-head but not color-coded:

df %>% 
  plot_ly(x = ~x, y = ~y, color = ~is_basis) %>%
  add_annotations(x = ~x, y = ~y, showarrow = TRUE, text = "", ax = 0, ay = 0,
                  axref = "x", ayref = "y", xref = "x", yref = "y")

So, my question is: Can I add an arrow head with add_segments? Or, can I style and color the arrows generated with add_annotations?


Solution

  • You can chose arrowhead and set the color of the arrow through the arguments arrowhead and arrowcolor in the function add_annotations(). If you set axref = "x" and ayref = "y" you also make sure that the lines start at origo if you set ax and ay to 0. Here's an example using a subset of the built-in dataset mtcars:

    enter image description here

    Complete code:

    library(plotly)
    library(dplyr)
    
    data <- mtcars[which(mtcars$am == 1 & mtcars$gear == 4),]
    #data <- data %>% filter(row.names(data) %in% c("Honda Civic", "Fiat X1-9", "Datsun 710"))
    #row.names(data) <- c("Honda Civic", "Fiat X1-9", "Datsun 710")
    
    p <- plot_ly(data, x = ~wt, y = ~mpg, type = 'scatter', mode = 'markers',
            marker = list(size = 2)) #%>%
    
    p <- p %>%
      add_annotations(x = data["Honda Civic","wt"],
                      y = data["Honda Civic","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='blue',
                      arrowhead = 1,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p <- p %>%
      add_annotations(x = data["Fiat X1-9","wt"],
                      y = data["Fiat X1-9","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='green',
                      arrowhead = 2,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p <- p %>%
      add_annotations(x = data["Datsun 710","wt"],
                      y = data["Datsun 710","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='red',
                      arrowhead = 3,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p <- p %>%
      add_annotations(x = data["Fiat 128","wt"],
                      y = data["Fiat 128","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='black',
                      arrowhead = 4,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p <- p %>%
      add_annotations(x = data["Mazda RX4 Wag","wt"],
                      y = data["Mazda RX4 Wag","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='purple',
                      arrowhead = 5,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    
    p <- p %>%
      add_annotations(x = data["Volvo 142E","wt"],
                      y = data["Volvo 142E","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='grey',
                      arrowhead = 6,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p <- p %>%
      add_annotations(x = data["Toyota Corolla","wt"],
                      y = data["Toyota Corolla","mpg"],
                      text = "",
                      xref = "x",
                      yref = "y",
                      showarrow = TRUE,
                      arrowcolor='aquamarine',
                      arrowhead = 7,
                      arrowsize = 2,
                      ax = 0,
                      ay = 0,
                      axref="x",
                      ayref='y',
                      font = list(color = '#264E86',
                                  family = 'sans serif',
                                  size = 14))
    
    p