Unfortunately ggplot
is not interactive but it can be easily “fixed” with plotly
package. You only need to replace plotOutput
with plotlyOutput
and then render a plot on with renderPlotly
.
Example 1: plotly
library(shiny)
library(ggplot2)
library(plotly)
ui <- fluidPage(
plotlyOutput("distPlot")
)
server <- function(input, output) {
output$distPlot <- renderPlotly({
ggplot(iris, aes(Sepal.Width, Petal.Width)) +
geom_line() +
geom_point()
})
}
shinyApp(ui = ui, server = server)
Example 2: plotOutput(…, hoverOpts(id = “plot_hover”, delay = 50)):
We don’t have to use any special package to introduce the interactivity to our graphs though. All we need is our lovely shiny shiny
! We can just play with plotOutput
options as for instance click
, hover
or dblclick
to make the plot interactive. (See more examples in shiny gallery)
In the example below we add “hovering” by the parameterhover
and then customise delay, which is set by default 300ms.
plotOutput("distPlot", hover = hoverOpts(id = "plot_hover", delay = 50))
We then can access values via input$plot_hover
and use a function nearPoints
to show values that are near the points.
ui <- fluidPage(
selectInput("var_y", "Y-Axis", choices = names(iris)),
# plotOutput("distPlot", hover = "plot_hover", hoverDelay = 50), # UPDATED
# plotOutput in shiny 1.7.2 doesn't have the hoverDelay argument. One needs to use hoverOpts()
plotOutput("distPlot", hover = hoverOpts(id = "plot_hover", delay = 50)),
uiOutput("dynamic")
)
server <- function(input, output) {
output$distPlot <- renderPlot({
req(input$var_y)
ggplot(iris, aes_string("Sepal.Width", input$var_y)) +
geom_point()
})
output$dynamic <- renderUI({
req(input$plot_hover)
verbatimTextOutput("vals")
})
output$vals <- renderPrint({
hover <- input$plot_hover
# print(str(hover)) # list
y <- nearPoints(iris, input$plot_hover)[input$var_y]
req(nrow(y) != 0)
y
})
}
shinyApp(ui = ui, server = server)
Example 3: Custom ggplot2 tooltip:
The second solution works great but yes…we want to do it better! And yes…we can do it better! (…If we use some javaScript but pssssss don’t tell anyone!).
library(shiny)
library(ggplot2)
ui <- fluidPage(
tags$head(tags$style('
#my_tooltip {
position: absolute;
width: 300px;
z-index: 100;
padding: 0;
}
')),
tags$script('
$(document).ready(function() {
// id of the plot
$("#distPlot").mousemove(function(e) {
// ID of uiOutput
$("#my_tooltip").show();
$("#my_tooltip").css({
top: (e.pageY + 5) + "px",
left: (e.pageX + 5) + "px"
});
});
});
'),
selectInput("var_y", "Y-Axis", choices = names(iris)),
plotOutput("distPlot", hover = hoverOpts(id = "plot_hover", delay = 50)),
uiOutput("my_tooltip")
)
server <- function(input, output) {
output$distPlot <- renderPlot({
req(input$var_y)
ggplot(iris, aes_string("Sepal.Width", input$var_y)) +
geom_point()
})
output$my_tooltip <- renderUI({
hover <- input$plot_hover
y <- nearPoints(iris, input$plot_hover)[input$var_y]
req(nrow(y) != 0)
verbatimTextOutput("vals")
})
output$vals <- renderPrint({
hover <- input$plot_hover
y <- nearPoints(iris, input$plot_hover)[input$var_y]
req(nrow(y) != 0)
y
})
}
shinyApp(ui = ui, server = server)
Example 4: ggvis and add_tooltip:
We can also use ggvis
package. This package is great, however, not enough mature yet.
Update: ggvis
is currently dormant: https://github.com/rstudio/ggvis#status
library(ggvis)
ui <- fluidPage(
ggvisOutput("plot")
)
server <- function(input, output) {
iris %>%
ggvis(~Sepal.Width, ~Petal.Width) %>%
layer_points() %>%
layer_lines() %>%
add_tooltip(function(df) { paste0("Petal.Width: ", df$Petal.Width) }) %>%
bind_shiny("plot")
}
shinyApp(ui = ui, server = server)
EDITED
Example 5:
After this post I searched internet to see whether it could be done more nicely than example 3. I found this wonderful custom tooltip for ggplot and I believe it can hardly be done better than that.
Updated: it can happen that the shiny function p
gets masked by some other function and the shiny code doesn’t work properly. In order to avoid the issue, once can run the following command before sourcing the full shiny code:
p <- shiny::p
EDITED 2
The four first examples have been updated as of 03.09.2022 such that they are working with the newest shiny
version 1.7.2.