Plotly: Annotate outliers with sample names in boxplot

后端 未结 4 1869
滥情空心
滥情空心 2021-01-06 16:09

I am trying to create a boxplot with ggplot and plotly with the dataset airquality where Month is on the x-axis and Ozone values are o

4条回答
  •  情歌与酒
    2021-01-06 16:21

    I've managed to achieve this with Shiny.

    library(plotly)
    library(shiny)
    library(htmlwidgets)
    library(datasets)
    
    # Prepare data ----
    data(airquality)
    # add months
    airquality$Month <- factor(airquality$Month,
                               labels = c("May", "Jun", "Jul", "Aug", "Sep"))
    # add sample names
    airquality$Sample <- paste0('Sample_', seq(1:nrow(airquality)))
    
    # Plotly on hover event ----
    addHoverBehavior <- c(
      "function(el, x){",
      "  el.on('plotly_hover', function(data) {",
      "    if(data.points.length==1){",
      "      $('.hovertext').hide();",
      "      Shiny.setInputValue('hovering', true);",
      "      var d = data.points[0];",
      "      Shiny.setInputValue('left_px', d.xaxis.d2p(d.x) + d.xaxis._offset);",
      "      Shiny.setInputValue('top_px', d.yaxis.l2p(d.y) + d.yaxis._offset);",
      "      Shiny.setInputValue('dx', d.x);",
      "      Shiny.setInputValue('dy', d.y);",
      "      Shiny.setInputValue('dtext', d.text);",
      "    }",
      "  });",
      "  el.on('plotly_unhover', function(data) {",
      "    Shiny.setInputValue('hovering', false);",
      "  });",
      "}")
    
    # Shiny app ----
    ui <- fluidPage(
      tags$head(
        # style for the tooltip with an arrow (http://www.cssarrowplease.com/)
        tags$style("
                   .arrow_box {
                        position: absolute;
                      pointer-events: none;
                      z-index: 100;
                      white-space: nowrap;
                      background: rgb(54,57,64);
                      color: white;
                      font-size: 14px;
                      border: 1px solid;
                      border-color: rgb(54,57,64);
                      border-radius: 1px;
                   }
                   .arrow_box:after, .arrow_box:before {
                      right: 100%;
                      top: 50%;
                      border: solid transparent;
                      content: ' ';
                      height: 0;
                      width: 0;
                      position: absolute;
                      pointer-events: none;
                   }
                   .arrow_box:after {
                      border-color: rgba(136, 183, 213, 0);
                      border-right-color: rgb(54,57,64);
                      border-width: 4px;
                      margin-top: -4px;
                   }
                   .arrow_box:before {
                      border-color: rgba(194, 225, 245, 0);
                      border-right-color: rgb(54,57,64);
                      border-width: 10px;
                      margin-top: -10px;
                   }")
      ),
      div(
        style = "position:relative",
        plotlyOutput("myplot"),
        uiOutput("hover_info")
      )
    )
    
    server <- function(input, output){
      output$myplot <- renderPlotly({
        airquality[[".id"]] <- seq_len(nrow(airquality))
        gg <- ggplot(airquality, aes(x=Month, y=Ozone, ids=.id)) + geom_boxplot()
        ggly <- ggplotly(gg, tooltip = "y")
        ids <- ggly$x$data[[1]]$ids
        ggly$x$data[[1]]$text <- 
          with(airquality, paste0(" sample: ", Sample, "
    ", " month: ", Month, "
    ", " ozone: ", Ozone))[ids] ggly %>% onRender(addHoverBehavior) }) output$hover_info <- renderUI({ if(isTRUE(input[["hovering"]])){ style <- paste0("left: ", input[["left_px"]] + 4 + 5, "px;", # 4 = border-width after "top: ", input[["top_px"]] - 24 - 2 - 1, "px;") # 24 = line-height/2 * number of lines; 2 = padding; 1 = border thickness div( class = "arrow_box", style = style, p(HTML(input$dtext), style="margin: 0; padding: 2px; line-height: 16px;") ) } }) } shinyApp(ui = ui, server = server)

提交回复
热议问题