Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I let the user draw a line manually on a scatter plot and print the slope and intercept using shiny and or plotly in R?

Tags:

r

shiny

plotly

First time I ask so please bare with me! I am trying to get the slope and intercept when the user draws a line manually on the scatter plot.

I tried using the layout(dragmode = 'drawline') but it does not work. Instead I used the layout(dragmode = 'select') and that worked to get the slope and intercept. However does not allow the user to draw the line.

Here's what I tried

library(shiny)
library(plotly)

ui <- fluidPage(
  plotlyOutput("plot"),
  verbatimTextOutput("output")
)

server <- function(input, output) {
  output$plot <- renderPlotly({
    plot_ly(mtcars, x = ~wt, y = ~mpg) %>%
      add_markers() %>%
      layout(dragmode = "select")
  })
  
  output$output <- renderPrint({
    d <- event_data("plotly_selected")
    if (is.null(d)) "Select a region by clicking and dragging on the scatter plot"
    else {
      x <- d$x
      y <- d$y
      coef(lm(y ~ x))
    }
  })
}

shinyApp(ui, server)

Any help, recommendation or different way to do it will be much appreciated!

I am trying to get a line being drawn by the user ('manually') and get the slope and intercept printed.

like image 277
Jorge Roberto García Pastrana Avatar asked Dec 06 '25 15:12

Jorge Roberto García Pastrana


1 Answers

There are a lot of ways to do this. In my code, I've left the output you called for, where the slope and intercept and presented literally. Additionally, I add made the line of best-fit red.

I've added some comments in the code to explain the code's purpose, as well. Since it's really just rearranging what you've already written, it should be fairly straightforward.

Right now this line-of-best-fit will only extend the size of the selected data points, but it could extend across the entire graph. If there's something I've missed or that you thought of after you saw this, let me know.

library(shiny)
library(plotly)

ui <- fluidPage(
  plotlyOutput("plot"),
  verbatimTextOutput("output")
)

server <- function(input, output) {
  output$plot <- renderPlotly({
    d <- event_data("plotly_selected") # make event data available within render
    if(!is.null(d)) {
      x <- d$x
      y <- d$y
      coefs <- coef(lm(y~x))
    }
    
    plt <- plot_ly(mtcars, x = ~wt, y = ~mpg, name = "Points") %>%
      add_markers() %>%
      layout(dragmode = "select") 
    
    if (!is.null(d)) {           # if there's been a selection
      plt <- plt %>% 
        add_lines(data = data.frame(x = x,           # add line based on selection
                                    y = coefs[2] * x + coefs[1]), # mx + b
                  x = ~x, y = ~y, color = "red", name = "Line of<br>Fit")
    }
    plt                          # send plot to output
  })
  
  output$output <- renderPrint({
    d <- event_data("plotly_selected")
    if (is.null(d)) "Select a region by clicking and dragging on the scatter plot"
    else {
      x <- d$x
      y <- d$y
      coef(lm(y ~ x))
    }
  })
}

shinyApp(ui, server)

enter image description here

enter image description here

By the way, for your first question—this was fantastic!

like image 194
Kat Avatar answered Dec 08 '25 05:12

Kat



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!