aljabadi
aljabadi

Reputation: 543

R and Shiny: Show ggplot2 data values when hovering over the plot in Shiny

I have plot and next to it an interactive plot that updates the coordinate limits when user brushes on the plot. I need the interactive plot to show (on the plot) the data point values when hovered on (e.g. "The data belongs to ID X". has anyone had such problem? I included a reproducible chunk of my code and tried to make it fully relevant, but you can only focus on output$text. Would appreciate any help. Thanks

require(shiny)
require(ggplot2)


dat <-data.frame(seq(1,50, 1), seq(0,100,length.out = 50), sapply(seq(0,100,length.out = 50), function(x) x+3*rnorm(1,0,4)))
varlist <- c("ID", "IPRED", "DV")
names(dat) <- varlist

ui <- fluidPage(
  selectInput("y", "Y Variable", choices = varlist, selected = "IPRED" ),
  selectInput("x", "X Variable", choices = varlist, selected = "DV"),
  checkboxInput("dvpred", "Show Unity Line", value = TRUE),
  column(width=6,
         plotOutput("p1",
                    dblclick = "plot1_dblclick",
                    brush = brushOpts(
                      id = "plot1_brush",
                      resetOnNew = TRUE))
  ),
  column(width = 6,
         plotOutput("p12", hover = hoverOpts("p12_hover", delay = 100, delayType = "debounce"))),
  uiOutput("txt")
)

server <- function(input, output){

  pxy <- function(dataset, xvar, yvar, xlim=NULL, ylim=NULL){

    dat = subset(dataset, dat$DV<500)
    vmax <- max(max(dat[[xvar]]),max(dat[[yvar]]))
    vmin <- min(min(dat[[xvar]]),min(dat[[yvar]]))
    p <- ggplot(data = dat) + 
      geom_point(aes_string(x=xvar, y=yvar), size=2,shape=21, fill="blue") +
      labs(x=xvar, y=yvar) + ggtitle(paste0(yvar, " vs ", xvar)) +
      geom_hline(yintercept=0) +
      coord_cartesian(xlim = xlim, ylim = ylim, expand = TRUE)
    if ( input$dvpred)(p <- p  + xlim(vmin, vmax)+ ylim(vmin, vmax) + geom_abline(slope=1) )
    return(p)
  }
  output$p1 <- renderPlot({
    xlength <- length(unique(dat[[input$x]]))
    if (xlength>12){
      return(pxy(dat, input$x, input$y))}
    else 
      return (bxplotxy(dat, input$x, input$y))
  })
  output$txt <- 
    renderPrint({
      if(!is.null(input$p21_hover)){
        hover=input$p21_hover
        dat$dist<-sqrt((hover$x-dat$DV)^2+(hover$y-dat$IPRED)^2)
        if (min(subset(dat, !is.na(dist))$dist)<4)
          cat("This Data Point Belongs to the Patient ID: ", dat$ID[which.min(dat$dist)])
      }


    })
  ranges <- reactiveValues(x = NULL, y = NULL)
  output$p12 <- renderPlot({
    xlength <- length(unique(dat[[input$x]]))
    if (xlength>12){
      return(pxy(dat, input$x, input$y, ranges$x, ranges$y))}
    else 
      return (NULL)
  }) 
  observe({
    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
    }
  })

}
shinyApp(ui, server)

Upvotes: 2

Views: 3863

Answers (1)

SOwla
SOwla

Reputation: 386

I think you should be using verbatimTextOutput("txt") with output$txt <- renderPrint({ ... }), rather than uiOutput("txt"). But this would give you a text output outside of the plot, which doesn't sound like what you want..?

hovered points information would show in the verbatimTextOutput below the graphs, rather than on the graphs

If you want the text to appear next to the cursor as you hover, there's a ggplot2 extension called ggiraph: http://davidgohel.github.io/ggiraph/index.html. But I'm not sure it's compatible with brushing.

So I agree with Keqiang Li's suggestion to use plotly. The brushed information is different from ggplot, so you might find this example helpful: https://plot.ly/r/shinyapp-linked-brush/

Good luck!

Upvotes: 1

Related Questions