## ----setup, echo = FALSE, message = FALSE, warning = FALSE-------------------- knitr::opts_chunk$set(fig.width = 6, fig.height = 3, fig.align = "center") library(ggalluvial) pdf(NULL) ## ----run wide app locally, eval = FALSE--------------------------------------- # shiny::shinyAppDir(system.file("examples/ex-shiny-wide-data", package="ggalluvial")) ## ----pseudocode, eval = FALSE------------------------------------------------- # # '<(1) Load data.>' # # '<(2) Create "ggplot" object for alluvial plot and build it.>' # # '<(3) Extract data from built plot object used to create alluvium polygons.>' # # for (polygon in polygons) { # '<(4) Use polygon splines to generate coordinates of alluvium boundaries.>' # } # # '<(5) Define range of coordinates in grid units and plot units.>' # # for (polygon in polygons) { # '<(6) Convert coordinates from grid units to plot units.>' # } # # ui <- fluidPage( # '<(7) Output plot with hovering enabled.>' # # '<(8) Output tooltip.>' # ) # # # server <- function(input, output, session) { # # output$alluvial_plot <- renderPlot({ # '<(9) Render the plot.>' # }) # # output$tooltip <- renderText({ # if ('<(10) mouse cursor is within the plot panel>') { # if ('<(11) mouse cursor is within a stratum box>') { # '<(11b) Render stratum tooltip.>' # } else { # if ('<(12) mouse cursor is within an alluvium polygon>') { # '<(12b) Render alluvium tooltip.>' # } # } # } # }) # # } ## ----load dataset, eval = FALSE----------------------------------------------- # data(UCBAdmissions) # ucb_admissions <- as.data.frame(UCBAdmissions) ## ----set options, eval = FALSE------------------------------------------------ # # Offset, in pixels, for location of tooltip relative to mouse cursor, # # in both x and y direction. # offset <- 5 # # Width of node boxes # node_width <- 1/4 # # Width of alluvia # alluvium_width <- 1/3 ## ----draw and build plot, eval = FALSE---------------------------------------- # # Draw plot. # p <- ggplot(ucb_admissions, # aes(y = Freq, axis1 = Gender, axis2 = Dept)) + # geom_alluvium(aes(fill = Admit), knot.pos = 1/4, width = alluvium_width) + # geom_stratum(width = node_width, reverse = TRUE, fill = 'black', color = 'grey') + # geom_label(aes(label = after_stat(stratum)), # stat = "stratum", # reverse = TRUE, # size = rel(2)) + # theme_bw() + # scale_fill_brewer(type = "qual", palette = "Set1") + # scale_x_discrete(limits = c("Gender", "Dept"), expand = c(.05, .05)) + # scale_y_continuous(expand = c(0, 0)) + # ggtitle("UC Berkeley admissions and rejections", "by sex and department") + # theme(plot.title = element_text(size = rel(1)), # plot.subtitle = element_text(size = rel(1)), # legend.position = 'bottom') # # # Build the plot. # pbuilt <- ggplot_build(p) ## ----get xsplines and draw curves, eval = FALSE------------------------------- # # Add width parameter, and then convert built plot data to xsplines # data_draw <- transform(pbuilt$data[[1]], width = alluvium_width) # groups_to_draw <- split(data_draw, data_draw$group) # group_xsplines <- lapply(groups_to_draw, # data_to_alluvium) # # # Convert xspline coordinates to grid object. # xspline_coords <- lapply( # group_xsplines, # function(coords) grid::xsplineGrob(x = coords$x, # y = coords$y, # shape = coords$shape, # open = FALSE) # ) # # # Use grid::xsplinePoints to draw the curve for each polygon # xspline_points <- lapply(xspline_coords, grid::xsplinePoints) ## ----get coordinate ranges, eval = FALSE-------------------------------------- # # Define the x and y axis limits in grid coordinates (old) and plot # # coordinates (new) # xrange_old <- range(unlist(lapply( # xspline_points, # function(pts) as.numeric(pts$x) # ))) # yrange_old <- range(unlist(lapply( # xspline_points, # function(pts) as.numeric(pts$y) # ))) # xrange_new <- c(1 - alluvium_width/2, max(pbuilt$data[[1]]$x) + alluvium_width/2) # yrange_new <- c(0, sum(pbuilt$data[[2]]$count[pbuilt$data[[2]]$x == 1])) ## ----transform coordinates, eval = FALSE-------------------------------------- # # Define function to convert grid graphics coordinates to data coordinates # new_range_transform <- function(x_old, range_old, range_new) { # (x_old - range_old[1])/(range_old[2] - range_old[1]) * # (range_new[2] - range_new[1]) + range_new[1] # } # # # Using the x and y limits, convert the grid coordinates into plot coordinates. # polygon_coords <- lapply(xspline_points, function(pts) { # x_trans <- new_range_transform(x_old = as.numeric(pts$x), # range_old = xrange_old, # range_new = xrange_new) # y_trans <- new_range_transform(x_old = as.numeric(pts$y), # range_old = yrange_old, # range_new = yrange_new) # list(x = x_trans, y = y_trans) # }) ## ----ui, eval = FALSE--------------------------------------------------------- # ui <- fluidPage( # fluidRow(tags$div( # style = "position: relative;", # plotOutput("alluvial_plot", height = "650px", # hover = hoverOpts(id = "plot_hover") # ), # htmlOutput("tooltip"))) # ) ## ----renderPlot, eval = FALSE------------------------------------------------- # output$alluvial_plot <- renderPlot(p, res = 200) ## ---- eval = FALSE------------------------------------------------------------ # output$tooltip <- renderText( # if(!is.null(input$plot_hover)) { ... } # ... # ) ## ---- eval = FALSE------------------------------------------------------------ # hover <- input$plot_hover # x_coord <- round(hover$x) # # if(abs(hover$x - x_coord) < (node_width / 2)) { ... } else { ... } ## ---- eval = FALSE------------------------------------------------------------ # node_row <- # pbuilt$data[[2]]$x == x_coord & hover$y > pbuilt$data[[2]]$ymin & hover$y < pbuilt$data[[2]]$ymax ## ---- eval = FALSE------------------------------------------------------------ # node_label <- pbuilt$data[[2]]$stratum[node_row] # node_n <- pbuilt$data[[2]]$count[node_row] ## ----render strata tooltip, eval = FALSE-------------------------------------- # renderTags( # tags$div( # node_label, tags$br(), # "n =", node_n, # style = paste0( # "position: absolute; ", # "top: ", hover$coords_css$y + offset, "px; ", # "left: ", hover$coords_css$x + offset, "px; ", # "background: gray; ", # "padding: 3px; ", # "color: white; " # ) # ) # )$html ## ----test within polygon, eval = FALSE---------------------------------------- # hover_within_flow <- sapply( # polygon_coords, # function(pol) point.in.polygon(point.x = hover$x, # point.y = hover$y, # pol.x = pol$x, # pol.y = pol$y) # ) ## ---- eval = FALSE------------------------------------------------------------ # if (any(hover_within_flow)) { ... } ## ----info for alluvia tooltip, eval = FALSE----------------------------------- # coord_id <- rev(which(hover_within_flow == 1))[1] # flow_label <- paste(groups_to_draw[[coord_id]]$stratum, collapse = ' -> ') # flow_n <- groups_to_draw[[coord_id]]$count[1] ## ----render alluvia tooltip, eval = FALSE------------------------------------- # renderTags( # tags$div( # flow_label, tags$br(), # "n =", flow_n, # style = paste0( # "position: absolute; ", # "top: ", hover$coords_css$y + offset, "px; ", # "left: ", hover$coords_css$x + offset, "px; ", # "background: gray; ", # "padding: 3px; ", # "color: white; " # ) # ) # )$html ## ----run long app locally, eval = FALSE--------------------------------------- # shiny::shinyAppDir(system.file("examples/ex-shiny-long-data", package="ggalluvial"))