Search code examples
rplotplotlyr-plotlyline-plot

How can I successively add multiple lines to a graph in a plotly animation?


I want to show multiple lines being added to a plotly plot (as an animation) using R. For example, I have the following plotly line graphs (p, p2, p3):

library(plotly)
set.seed(3)
x = 1:10
y = 1:10
y2 = y^2
y3 = y^3
p = plot_ly(data = data.frame(x = x, y = y), x = ~ x, y = ~y, type = "scatter", mode = "lines")
p2 = plot_ly(data = data.frame(x = x, y = y2), x = ~ x, y = ~y2, type = "scatter", mode = "lines")
p3 = plot_ly(data = data.frame(x = x, y = y3), x = ~ x, y = ~y3, type = "scatter", mode = "lines")

Here p, p2, p3 are different plots but they all have the same x axis and different y axis. I want to be able to make an animation where the lines y, y2, y3 will successively appear in the plotly graph.

P.S: It does not strictly have to be done using plotly, but strongly preferred.


Solution

  • An idea might be to create a 'dataset' for each frame.
    The first frame contains all values for y and all values for y2 and y3 are located outside the y-axis limits. For the second frame all values from y and y2 are shown and just the values from y3 are beyond the limit. In frame 3 all values are included.

    library(tidyverse)
    library(plotly)
    
    # transform dataframe into a long format
    df <- data.frame(x = 1:10,
                     y = 1:10) %>%
      mutate(y2 = y^2,
             y3 = y^3) %>%
      pivot_longer(cols = -x,
                   names_to = "line",
                   values_to = "value")
    
    # set the values for each frame and line 
    # (all lines not shown, need to hidden outside the plot limits - NA won't work)
    df_plot <- map_df(1:3,  ~ mutate(df, frame = .)) %>% 
      mutate(value = case_when(frame == 1 & line %in% c("y2", "y3") ~ -10,
                               frame == 2 & line %in% c("y3") ~ -10,
                               TRUE ~ value))
    
    # create plot
    plot_ly(data = df_plot, 
            x = ~x,
            y = ~value,
            color = ~line,
            type = "scatter",
            mode = "line",
            frame = ~frame)  %>%
      layout(yaxis=list(range = c(0, 1000))) %>%
      animation_opts(easing = "bounce")