Hello – I need to generate some output
values dynamically (i.e. a set of ggplot2 plots via renderPlot
). What plots get drawn depends on an input
value (so afaik the output
assignments need to happen in a reactive context).
Each plot needs to be "independent" so I cannot just combine them with {patchwork}/{cowplot} as one single reactive value and assign it outside of observe()
to a single/always-the-same output
name.
My current understanding of mutating object in R in nested functions is that you cannot do it without a global assignment.
try_to_mutate <- function(l) {
print(pryr::where("l"))
purrr::walk(1:2, function(i) {
l[[as.character(i)]] <- i # would work on parent l with <<-
print(pryr::where("l"))
})
l
}
a_list <- list()
new_list <- try_to_mutate(a_list)
identical(a_list, new_list)
[1] TRUE
Here new_list
will not be changed after try_to_mutate()
, as the mutations happening in purrr::walk
's function seem scoped to that function envs. I wouldn't try to modify a list this way usually but in the shiny reprex below, it's the only way I found.
Now, in shiny, it seems that the reprex below work and I cannot explain why.
Here is a reprex:
library(shiny)
library(dplyr)
library(purrr)
library(ggplot2)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("species", "Choose species",
unique(iris$Species),
multiple = TRUE)
),
mainPanel(uiOutput("plots"))
)
)
server <- function(input, output) {
output$plots <- renderUI({
plot_output_list <- purrr::map(input$species, function(sp) {
plotOutput(paste0("plot_", sp))
})
do.call(tagList, plot_output_list) # needed to display properly.
plot_output_list
})
observe({
purrr::walk(input$species,
function(sp) {
plot_data <- filter(iris, Species == sp)
output[[paste0("plot_", sp)]] <- renderPlot({
ggplot(plot_data, aes(x = Sepal.Length, y = Sepal.Width)) +
geom_point() +
labs(title = sp)
})
})
})
}
shinyApp(ui = ui, server = server)
I don't understand why it works with output[[paste0("plot_", sp)]] <-
. I thought I would need at least a double arrow (<<-
) to access output
.
Thanks a lot