Reputation: 33
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
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
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