6

I would like to add a line (not just vertical or horizontal) to a plotly chart

library(plotly)
d = data.frame(x=1:10, y=1:10)
plot_ly(d, x = ~x, y = ~y, type='scatter')

Say I want (D) y = 2x as a line is there a way for me to plot without generating the data myself in another column of d

statquant
  • 13,672
  • 21
  • 91
  • 162
  • 1
    Are you looking for something like `plot_ly(d, x = ~x, y = ~y, type='scatter', mode = "markers") %>% add_trace(x = ~2*x, y = ~y, mode = "lines")` – Jota Feb 01 '17 at 14:54
  • yes, but what if I have several graphs and I do not know the `xlim` of the 'widest' sub-plot, I might end up with a line that does not 'cover' the whole graph – statquant Feb 01 '17 at 14:58
  • Add on one of these? `%>% layout(xaxis = list(range = c(~min(x), ~max(x))))`? I might need another example if this isn't getting at the problem. – Jota Feb 01 '17 at 15:15
  • Did not know that, I'll check asap – statquant Feb 01 '17 at 15:30
  • [Here](https://stackoverflow.com/questions/34093169/horizontal-vertical-line-in-plotly) a related post can be found. – ismirsehregal Apr 07 '22 at 11:02

2 Answers2

5

There at least two ways of simulating abline.

  • Add another trace with the start and end point
  • Add a line shape to the layout with the start and end point

The disadvantage is that the min and max for each trace needs to be calculated (Plotly needs to do that anyway but it bloats the code).

The alternative would be draw the line from one extreme to the other other and then set the xaxis and yaxis range manually.

In the example below the red line is the added trace, while the black line is added via shape line.

enter image description here

library('plotly')

#a function to calculate your abline
p_abline <- function(x, a=2, b=-5){
  y <- a * x + b
  return(y)
}

#create an empty plot    
p <- plot_ly()

#list with all your x and y values
x <-  list(c(1,2,3), c(2,3,6), (1:5))
y <-  list(c(1,2,3), c(0,5,10), sample(-10:10, 5))

#loop through the x/y values and determine min/max
for (i in 1:length(x)) {
  p<-add_trace(p, y=y[[i]], x=x[[i]] , type="scatter", mode="markers+lines")
  if (i == 1 || max(x[[i]]) > max_x) {
    max_x = max(x[[i]])
  }
  if (i == 1 || max(y[[i]]) > max_y) {
    max_y = max(y[[i]])
  }
  if (i == 1 || min(x[[i]]) < min_x) {
    min_x = min(x[[i]])
  }
  if (i == 1 || min(y[[i]]) < min_y) {
    min_y = min(y[[i]])
  }

}

#add a trace to simulate abline
p<-add_trace(p, x=c(min_x, max_x), y=c(p_abline(min_x), p_abline(max_x)) , type="scatter", mode="lines", name='abline')

#add a shape (line) to simulate abline
p <- p %>% layout(
  shapes=list(type='line', x0=min_x, x1=max_x, y0=p_abline(min_x, -1, 3), y1=p_abline(max_x, -1, 3))
  )

p
Maximilian Peters
  • 30,348
  • 12
  • 86
  • 99
2
library(plotly)
d = data.frame(x=1:10, y=1:10)
plot_ly(d, x = ~x, y = ~y, type='scatter') %>%
  add_trace(d, x = ~x, y = ~x * 2, type = "scatter")

It turns out you can do math right within the add_trace function call where you're saying what y should be. So you can tell plotly to just multiply that column by two right in the argument.

Adrian Martin
  • 780
  • 7
  • 21