Search code examples
rggplot2plotlyscatter-plotr-plotly

Creating ribbons with plotly


I need to draw two slopes of acceleration-vs-mpg over the scatter plot, one slope for light cars and one slope for heavy cars. I created this:

cars_light <- cars_log[cars_log$log.weight. <= log(mean(cars$weight)), ]
cars_heavy <- cars_log[cars_log$log.weight. > log(mean(cars$weight)),]
cars_log$wt_cat <- ifelse(cars_log$log.weight. > log(mean(cars$weight)), 'heavy', 'light')

Until now I have created the scatter plot by doing this:

    plot_ly(
  data = cars_log,
  type = "scatter",
  x = ~log.acceleration.,
  y = ~ log.mpg.,
  color = ~ factor(wt_cat),
  colors = c("#8bc34a", "#ff5722"),
  marker = list(size = 10, opacity = 0.6)
) %>%
  layout(title = "Heavy cars VS light cars")

Which gives me this result:

enter image description here

Now, I want to create a slope for heavy cars and another one for light cars, I know that I need to use add_ribbons trace of plotly but I can't figure it out how to generate that. I am having problems computing lm with plotly. I could do the same with ggplot but I don't know how to do that with plotly..

    ggplot(cars_log, aes_string('log.acceleration.', 'log.mpg.')) +
  geom_point(aes(color = factor(wt_cat))) +
  geom_smooth(method = 'lm', aes(color = factor(wt_cat)))

This is a sample of my data:

    > cars_log[1:5,]
  log.mpg. log.cylinders. log.displacement. log.horsepower. log.weight. log.acceleration. model_year origin
1 2.890372       2.079442          5.726848        4.867534    8.161660          2.484907         70      1
2 2.708050       2.079442          5.857933        5.105945    8.214194          2.442347         70      1
3 2.890372       2.079442          5.762051        5.010635    8.142063          2.397895         70      1
4 2.772589       2.079442          5.717028        5.010635    8.141190          2.484907         70      1
5 2.833213       2.079442          5.710427        4.941642    8.145840          2.351375         70      1

Solution

  • You can use the add_ribbons() function. Its main three arguments are:

    • data the data
    • x x values
    • ymin the lower bound of the ribbon
    • ymax the upper bound of the ribbon

    Due to lack of a minimal data set, I took this one: plotly regression line R which was used in a close question (i.e. drawing regression line in R Plotly). Using this data set, here is an example where the regression is done outside Plotly, its output formatted using broom::augment() and then used to create the ribbon:

    library(plotly)
    library(broom)
    data(airquality)
    airq <- airquality %>% 
          filter(!is.na(Ozone))
    fit <- lm(Ozone ~ Wind, data = airq)
    airq %>% 
      plot_ly(x = ~Wind, name = 'Scatter') %>% 
      add_markers(y = ~Ozone) %>% 
      add_ribbons(data = augment(fit,se_fit = TRUE),
                  ymin = ~.fitted - 1.96 * .se.fit,
                  ymax = ~.fitted + 1.96 * .se.fit,
                  line = list(color = 'rgba(7, 164, 181, 0.05)'),
                  fillcolor = 'rgba(7, 164, 181, 0.2)',
                  name = '95% ribbon')
    

    Which gives the following plot: enter image description here