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(..., hover = "plot_hover"):
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 hover = "plot_hover"
and then specify delay which is by default 300ms.
plotOutput("distPlot", hover = "plot_hover", hoverDelay = 0)
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 = 0),
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 = "plot_hover", hoverDelay = 0),
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.