Search code examples
rplotlyr-plotly

R plotly customization of multiple line plot


I have the following sample dataframe and I'm using Plotly in my R Shiny app to create a multi line plot:

df2=data.frame(DATE=as.Date(c('2022-01-04','2022-01-08','2022-02-06','2022-01-12','2022-02-15','2022-01-25','2022-02-08')), 
             QUANTITY=c(50,50,50,120,120,70,50), 
             PRICE=c(111,112, 104,90,93,98,105), TYPE=c('summer','summer','summer','summer','summer','winter','winter'),
             COLOR=c('blue','blue','blue','blue','blue','red','red'))


  plot_ly(df2, x = ~eval(parse(text='DATE')), 
                 y = ~eval(parse(text='PRICE')), color = ~eval(parse(text='COLOR')), connectgaps = TRUE) %>% add_lines()  

The three questions I have are the following:

  1. why the color doesn't work? I'm getting lines that are blue and green.
  2. I would need to use column 'QUANTITY' to determine the thickness of the lines. For example, one line should be given by quantity = 50 and color = blue and a different line (thicker) by quantity = 120 and color = blue.
  3. Is it possible to have for example one line being line+markers and another line being only markers and pass this info as a column of the dataframe? Thanks.

Solution

  • color defines a variable to group colors by; colors is for designating a specific color.

    For example,

    plot_ly(df2, x = ~DATE, y = ~PRICE, 
            color = ~COLOR, colors = ~COLOR,
            type = "scatter", mode = "markers+lines")
    

    enter image description here

    If you wanted the line size by quantity, you would need separate traces. If you wanted to include markers by color, you need to do that with separate traces. The following code does this. However, there was only 1 red at QUANTITY 50, and only 1 red at QUANTITY 70. Therefore, despite calling for lines, there is no line using this example data.

    p <- plot_ly()
    
    lapply(1:length(unique(df2$QUANTITY)),
           function(j){
             lapply(1:length(unique(df2$COLOR)),
                    function(k){
                      cols <- unique(df2$COLOR)[k]
                      
                      if(cols == "blue"){
                        p <<- p %>% 
                          add_lines(data = df2 %>% filter(COLOR == cols,
                                                          QUANTITY == unique(QUANTITY)[j]),
                                    x = ~DATE, y = ~PRICE, color = I(cols),
                                    line = list(width = 3 * (unique(df2$QUANTITY)[j]/100)))
                      }
                      if(cols == "red"){
                        p <<- p %>% 
                          add_trace(data = df2 %>% filter(COLOR == cols,
                                                          QUANTITY == unique(QUANTITY)[j]),
                                    x = ~DATE, y = ~PRICE, color = I(cols),
                                    line = list(width = 3 * (unique(df2$QUANTITY)[j]/100)),
                                    type = "scatter", mode = "markers+lines")
                      }
                    })
           })
    p
    

    enter image description here

    If I take your expand on the example data, then use this code, it looks more obvious.

    df3 <- data.frame(rbind(df2, df2 %>% mutate(PRICE = PRICE + 10, DATE = DATE + 4)))
    p <- plot_ly()
    lapply(1:length(unique(df3$QUANTITY)),
           function(j){
             lapply(1:length(unique(df3$COLOR)),
                    function(k){
                      cols <- unique(df3$COLOR)[k]
                      
                      if(cols == "blue"){
                        p <<- p %>% 
                          add_lines(data = df3 %>% filter(COLOR == cols,
                                                          QUANTITY == unique(QUANTITY)[j]),
                                    x = ~DATE, y = ~PRICE, color = I(cols),
                                    line = list(width = 3 * (unique(df3$QUANTITY)[j]/100)))
                      }
                      if(cols == "red"){
                        p <<- p %>% 
                          add_trace(data = df3 %>% filter(COLOR == cols,
                                                          QUANTITY == unique(QUANTITY)[j]),
                                    x = ~DATE, y = ~PRICE, color = I(cols),
                                    line = list(width = 3 * (unique(df3$QUANTITY)[j]/100)),
                                    type = "scatter", mode = "markers+lines")
                      }
                    })
           })
    p
    

    enter image description here