Sydney Sydney - 2 months ago 11
R Question

Need to access ggplot_build from renderPlot in Shiny R

So after much searching and research, I've determined that I have no idea how to make this work. Essentially what I want to do is access data generated by my plot by using ggplot_build. However, the plot is generated in Shiny through renderPlot, and so I can't access it elsewhere in the app.

So the closest thing I've come up with is declaring an empty reactiveValue and adding my whole plotting function in every time. This way, I'll be able to get to the plot object when I need to in order to get the data from ggplot_build.

The problem is that while it doesn't throw any errors, no plot will generate when I run my code. The code itself is below, and please keep in mind that this is an extremely simplified example of the plotting itself. The full version involves a significant amount more possible added geom_ terms, etc. Any help would be greatly appreciated. Thank you in advance.

As far as my data, it's in a csv and looks something like this:



Year,Field,Company,Hybrid,Yield,Moisture,Erect,DoP,DoH,RM,Stand,PPA
1934,Alhambra,Champion,White Pearl,9.1,39.5,NaN,2-May,20-Nov,NaN,NaN,NaN
1944,Galesburg,Pioneer,334,92.7,18.3,99.3,20-May,8-Nov,NaN,NaN,NaN
1945,Sheldon,Funk,G-169,70.6,24.3,39,25-May,8-Nov,NaN,NaN,NaN
1946,Galesburg,Doubet,D-42,100.8,22,94,24-May,8-Nov,NaN,NaN,NaN
1949,DeKalb,Ferris,F-11,51.3,18.4,91,23-May,16-Nov,NaN,72,NaN





And code:



Variable_Extractor <- function(dataset) {
vars = names(dataset)
for (i in vars) {
if (is.factor(dataset[[i]][1]) == TRUE) {
vars = vars[vars != i]
}
}
return(vars)
}

Identify_Min_Max <- function(dataset, var) { #var must be a string column name
a = min(dataset[[var]], na.rm = TRUE)
b = max(dataset[[var]], na.rm = TRUE)
return(c(a,b))
}

ui <- fluidPage(
titlePanel('Illinois Yield Trials'),

sidebarLayout(position = 'left',
sidebarPanel(
selectInput('var', 'Choose variable',
c('Choose one' = '', Variable_Extractor(agridata))),
uiOutput('histslider'),
numericInput('bin_width', 'Enter binwidth',
value = 5, min = 0, max = 1000)),

mainPanel(div(style = "position:relative",
plotOutput('plot')))
)
)

server <- function(input, output) {

output$histslider <- renderUI({
valhist <- Identify_Min_Max(agridata, toString(input$var))
sliderInput(inputId = 'sliderhist',
label = paste("Select values for ", input$var, sep = ''),
min=valhist[1],
max=valhist[2],
value=valhist,
sep= '')
})

plt <- reactiveValues()

output$plot <- renderPlot({
plt$p <- ggplot()
agridatasub <- subset(agridata, agridata[[input$var]] >= input$sliderhist[1] & agridata[[input$var]] <= input$sliderhist[2])
plt$p <- plt$p + geom_histogram(data=agridatasub, aes_string(x=input$var), binwidth = input$bin_width,
color = 'black', fill = 'gray75')
return(plt$p)
})

}

shinyApp(ui=ui, server=server)




Answer

You don't need to use reactiveValues that way, you can just:

plt <- reactive({
agridatasub <- subset(agridata, agridata[[input$var]] >= input$sliderhist[1] & agridata[[input$var]] <= input$sliderhist[2])
  ggplot() + geom_histogram(data=agridatasub, aes_string(x=input$var), binwidth = input$bin_width, 
                                  color = 'black', fill = 'gray75')  
})
output$plot <- renderPlot({
  plt()
})

A full example using iris instead of your dataset:

Variable_Extractor <- function(dataset) {
  vars = names(dataset)
  for (i in vars) {
    if (is.factor(dataset[[i]][1]) == TRUE) {
      vars = vars[vars != i]
    }
  }
  return(vars)
}

Identify_Min_Max <- function(dataset, var) { #var must be a string column name
  a = min(dataset[[var]], na.rm = TRUE)
  b = max(dataset[[var]], na.rm = TRUE)
  return(c(a,b))
}
library(shiny)
ui <- fluidPage(
  titlePanel('Illinois Yield Trials'),

  sidebarLayout(position = 'left',
                sidebarPanel(
                  selectInput('var', 'Choose variable', 
                              c('Choose one' = '', Variable_Extractor(iris))),
                  uiOutput('histslider'),
                  numericInput('bin_width', 'Enter binwidth', 
                               value = 5, min = 0, max = 1000)),

                mainPanel(div(style = "position:relative",
                              plotOutput('plot')),
                          verbatimTextOutput("test"))
  )
)

server <- function(input, output) {

  output$histslider <- renderUI({
    valhist <- Identify_Min_Max(iris, toString(input$var))
    sliderInput(inputId = 'sliderhist', 
                label = paste("Select values for ", input$var, sep = ''),
                min=valhist[1], 
                max=valhist[2], 
                value=valhist,
                sep= '')
  })

  plt <- reactive({
    req(input$var)
    irissub <- subset(iris, iris[[input$var]] >= input$sliderhist[1] & iris[[input$var]] <= input$sliderhist[2])

    ggplot()  + geom_histogram(data=irissub, aes_string(x=input$var), binwidth = input$bin_width, 
                                    color = 'black', fill = 'gray75')
  })

  output$plot <- renderPlot({

    return(plt())
  })

  output$test <- renderPrint({
    req(input$var)
    str(ggplot_build(plt()))
  })

}

shinyApp(ui=ui, server=server)