Berthoz
Berthoz

Reputation: 113

Dynamic multiplots on the same graph with ggplot R Shiny

I am developing a shiny application which aims at comparing plots on the same graph and I want to use ggplot to be able to zoom in my graph.

The problem is the number of plots, which depends on the user selection. I want to plot the graphs with lines, here is what I have (working example) :

ui.R

shinyUI(fluidPage(   
  sidebarLayout(
    sidebarPanel(          
      fluidRow( 

        #checkboxGroupInput
        column((5), 
               checkboxGroupInput("model", 
                                  label = h3("Choix du modele"), 
                                  choices = c("1","2","3"),
                                  selected = 8)
        )            
      )         
    ),   
    mainPanel
    (
    fluidRow(
      column(width = 12, class = "well",
             h4("Brush and double-click to zoom"),
             plotOutput("plot1", height = 300,
                        dblclick = "plot1_dblclick",
                        brush = brushOpts(
                          id = "plot1_brush",
                          resetOnNew = TRUE
                        )
             )
      )
    )
    )
  )
)
)

server.R

# Here is the server part of Shiny 
library('shiny')
library(ggplot2)
library(reshape)
library(Cairo)

function(input, output) {


  ranges <- reactiveValues(x = NULL, y = NULL)

  output$plot1 <- renderPlot({

    tsPlot <- seq(from = ISOdate(2012,01,01,0,0,0), to = ISOdate(2012,01,01,23,45,0), by =60*15)
    measures <- runif(96)

    dataPlot <- data.frame(tsPlot,measures)
    list_models <- c("1","2","3")
    if(length(input$model) > 0)
    {
      nb = 0
      for(i in 1:length(list_models))
      {
        values <- runif(96)
        dataPlot<- cbind(dataPlot,values)
      }
    }
    dataPlot_melted <- melt(dataPlot,id="tsPlot")

    ggplot() + 
      geom_line(data=dataPlot_melted,aes(tsPlot,value)) +
      coord_cartesian(xlim = ranges$x, ylim = ranges$y)

  })

  # When a double-click happens, check if there's a brush on the plot.
  # If so, zoom to the brush bounds; if not, reset the zoom.
  observeEvent(input$plot1_dblclick, {
    brush <- input$plot1_brush
    if (!is.null(brush)) {
      ranges$x <- c(brush$xmin, brush$xmax)
      ranges$y <- c(brush$ymin, brush$ymax)

    } else {
      ranges$x <- NULL
      ranges$y <- NULL
    }
  })

}

The problem is solved if I want to plot points. I just have to use geom_point. But if I want to point lines, all the values are put in the same plot.

Does anyone know the trick to get out of this situation ?

Thanks in advance :)

Upvotes: 1

Views: 1299

Answers (1)

Berthoz
Berthoz

Reputation: 113

I found a solution. It's not really beautiful, but it works :

  dataPlot <- data.frame(tsPlot,measures,rep("Measures",length(tsPlot)))
  names(dataPlot) <- c("ts","value","name")

    list_models <- c("1","2","3")
    if(length(input$model) > 0)
    {
      nb = 0
      for(i in 1:length(list_models))
      {
        values <- runif(96)
        dataPlot2<- data.frame(dataPlot,values,rep(list_models[i],length(values)))
        names(dataPlot2) <- c("ts","value","name")
        dataPlot <- rbind(dataPlot,dataPlot2)
      }
    }

    x <- ggplot(data=dataPlot, aes(x=time, y=value, group=name, colour=factor(name)))+
   geom_line(size=.25) 

The trick relies on "group=name" in ggplot. We have only one column of values, but we also have a column of labels (name), which splits up correctly the data.

Upvotes: 2

Related Questions