Alo
Alo

Reputation: 33

R Shiny data not available "Error: object not found"

When plotting to barplots in a Shiny app, the dataframes generated are only available to the first but not the second plot ("Error: Object df2 not found"). Copying and pasting the code to generate the data frames into the second renderPlot part solves the issue but is redundant and slows down the app. Is there a more elegant way to make data available acorss multiple renderPlot parts? I tried to use Shinys reactive() function but without success.

Here's a minimal example:

library(shiny)
library(ggplot2)

# Define UI for application that draws a histogram
ui <- fluidPage(

  titlePanel("Utility"),

  sidebarLayout(
    sidebarPanel(
    sliderInput("var1",
                 "N",
                 min = 1,
                 max = 100,
                 value = 20)),
    mainPanel(
      plotOutput("barplot1"),
      plotOutput("barplot2"))))



# Define server logic required to draw a barplot
server <- function(input, output) {

  output$barplot1 <- renderPlot({

  df <- as.data.frame(matrix(c(
                      "A", "1", rnorm(1, input$var1, 1),
                      "A", "2", rnorm(1, input$var1, 1),
                      "B", "1", rnorm(1, input$var1, 1),
                      "B", "2", rnorm(1, input$var1, 1)),
                      nrow = 4, ncol=3, byrow = TRUE))
  df$V3 <- as.numeric(as.character(df$V3))

  df2 <- as.data.frame(matrix(c(
                       "A", "1", rnorm(1, input$var1, df[1,3]),
                       "A", "2", rnorm(1, input$var1, df[1,3]),
                       "B", "1", rnorm(1, input$var1, df[1,3]),
                       "B", "2", rnorm(1, input$var1, df[1,3])),
                       nrow = 4, ncol=3, byrow = TRUE))
  df2$V3 <- as.numeric(as.character(df$V3))

  ggplot(df, aes(x=V1, y=V3, fill=V2)) +
  geom_bar(stat="identity") 

  })

  output$barplot2 <- renderPlot({

  ggplot(df2, aes(x=V1, y=V3, fill=V2)) +
  geom_bar(stat="identity") 

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 3

Views: 4687

Answers (2)

kluu
kluu

Reputation: 2995

Yes, you should never duplicate your data. To make your dataframe available to all of your functions, just generate it dynamically using reactive (since it depends on input$var1). When calling a reactive variable x, you need to use x() instead of x. Otherwise, you get the error that you got: Error: object of type 'closure' is not subsettable". So in your case, making df reactive would require you to use df() instead.

server <- function(input, output) {

  df <- reactive(
    data.frame(V1 = c("A", "A", "B", "B"),
               V2 = c("1", "2", "1", "2"),
               V3 = rnorm(1, input$var1, 5)        
               )
  )

  output$barplot1 <- renderPlot({
    ggplot(df(), aes(x=V1, y=V3, fill=V2)) +
      geom_bar(stat="identity") 
  })

  output$barplot2 <- renderPlot({
    ggplot(df(), aes(x=V1, y=V3, fill=V2)) +
      geom_bar(stat="identity") 
  })
}

Upvotes: 1

s.brunel
s.brunel

Reputation: 1043

this one is working create data.frame outside in their own reactive

library(shiny)
library(ggplot2)

# Define UI for application that draws a histogram
ui <- fluidPage(

  titlePanel("Utility"),

  sidebarLayout(
    sidebarPanel(
      sliderInput("var1",
                  "N",
                  min = 1,
                  max = 100,
                  value = 20)),
    mainPanel(
      plotOutput("barplot1"),
      plotOutput("barplot2")
      )
    )
  )



# Define server logic required to draw a barplot
server <- function(input, output) {


  df <- reactive({


    df <-  as.data.frame(matrix(c(
      "A", "1", rnorm(1, input$var1, 1),
      "A", "2", rnorm(1, input$var1, 1),
      "B", "1", rnorm(1, input$var1, 1),
      "B", "2", rnorm(1, input$var1, 1)),
      nrow = 4, ncol=3, byrow = TRUE))
    df$V3 <- as.numeric(as.character(df$V3))

    df

  })

  df2 <- reactive({  

  df2 <- as.data.frame(matrix(c(
    "A", "1", rnorm(1, input$var1, df()[1,3]),
    "A", "2", rnorm(1, input$var1, df()[1,3]),
    "B", "1", rnorm(1, input$var1, df()[1,3]),
    "B", "2", rnorm(1, input$var1, df()[1,3])
    ),
    nrow = 4, ncol=3, byrow = TRUE))
   df2$V3 <- as.numeric(as.character(df()$V3))

  df2
  })

  output$barplot1 <- renderPlot({


    ggplot( df() , aes(x=V1, y=V3, fill=V2)) +
      geom_bar(stat="identity")

  })

  output$barplot2 <- renderPlot({


    ggplot(df2(), aes(x=V1, y=V3, fill=V2)) +
      geom_bar(stat="identity")

  })
}

# Run the application 
shinyApp(ui = ui, server = server)

Upvotes: 0

Related Questions