Are there global variables in R Shiny?
This page on the Shiny webpage explains scoping of Shiny variables.
Global variables can either be put in server.R
(as per Ricardo's answer) or in global.R
.
Objects defined in global.R are similar to those defined in server.R outside shinyServer(), with one important difference: they are also visible to the code in ui.R. This is because they are loaded into the global environment of the R session; all R code in a Shiny app is run in the global environment or a child of it.
In practice, there aren’t many times where it’s necessary to share variables between server.R and ui.R. The code in ui.R is run once, when the Shiny app is started and it generates an HTML file which is cached and sent to each web browser that connects. This may be useful for setting some shared configuration options.
How to make a local variable global in R using Shiny?
Just create the variable outside any sub-function and update its value using <<-
. This variable will be global per each session.
server <- function(input, output) {
# init variable here
algorithm_output <- NULL
out_plots <- eventReactive(input$ok_input, {
# to modify a global variable use <<- instead of <- or =
algorithm_output <<- some_global_function(3, 2, 1)
do.call("grid.arrange", c(algorithm_output$indexes, nrow=3))
})
output$indexes <- renderPlot({
out_plots()
})
out_means <- eventReactive(input$ok_means, {
k = as.integer(input$k)
# you can get access to the updated value of your variable
matplot(algorithm_output$means[[k-1]], type = "l", lty=1)
})
output$means <- renderPlot({
out_means()
})
}
R Shiny: global variable for all functions in server.R
The idea to use reactive is the right direction; however you didn't do it quite right. I just added one line and it is working:
shinyServer(function(input, output, session) {
df <- NULL
in_data <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
else df <<- read.csv(inFile$datapath, as.is=TRUE)
return(NULL)
})
output$frame <- renderTable({
call.me = in_data() ## YOU JUST ADD THIS LINE.
df
})
})
Why? Because a reactive object is very similar to a function, which gets executed only when you call it. Thus the 'standard' way of your code should be:
shinyServer(function(input, output, session) {
in_data <- reactive({
inFile <- input$file1
if (is.null(inFile)) return(NULL)
else read.csv(inFile$datapath, as.is=TRUE)
})
output$frame <- renderTable({
in_data()
})
})
R shiny clear global variables after shiny app ends
To run code on app stop you need to provide onStop
as an argument to shinyApp
(nested in the onStart
callback function).
If you place onStop
in the server function it will run after a session stops (e.g. closing the browser window).
Please check the following the see the difference:
library(shiny)
myGlobalVaribale <- "Some useful global content"
ui <- basicPage(p(myGlobalVaribale),
actionButton("stopSession", "Stop session"),
actionButton("stopApp", "Stop app")
)
server <- function(input, output, session) {
onStop(function() cat("This will run on session stop\n"))
observeEvent(input$stopSession, {
cat(sprintf("Closing session %s\n", session$token))
session$close()
})
observeEvent(input$stopApp, {
cat("Stopping shiny app\n")
stopApp()
})
}
shinyApp(ui, server,
onStart = function() {
cat("This will run on app start\n")
onStop(function() {
cat("This will run on app stop\n")
print(ls(envir = .GlobalEnv))
rm(list = c("myGlobalVaribale"), envir = .GlobalEnv)
print(ls(envir = .GlobalEnv))
})
}
)
R Shiny: Why can't functions from source files access global variables when running as an app?
Up front: use source("...", local = TRUE)
.
source
by default loads the file into the global environment, not the local environment. When you're working on your console, the two are the same. However, when you run the app, the app's environment is distinct, and not in the search-path for functions defined in the global environment.
Example:
main file:
global_var <- "Hello"
source("quux.R")quux.R
:func <- function() {
return(global_var)
}
When sourced, I see
# Error in func() (from quux.R#2) : object 'global_var' not found
Namely,
environment(func)
# <environment: R_GlobalEnv>
When I change the main file to
global_var <- "Hello"
source("quux.R", local = TRUE)
then sourcing it works, as does func()
by itself.
environment(func)
# <environment: 0x0000000054a995e0>
func()
# [1] "Hello"
How to assign global variables that can be accessed by other output$function in R shiny?
If you really want to assign something to global, you can use the <<-
operator. Or assign("x", value = data, envir = .GlobalEnv)
.
But, you really don't want to. It's almost never, ever a good idea. Especially since you need to make use of reactive inputs.
If sample_d <- data()
is too many keystrokes, just ignore assigning within the local environment (the output
object) and use data()
.
output$plot <- renderPlot({
plot(density(data()[,1]), main = input$title)
})
If you want an object with multiple values, a list of objects, make your reactive object into a list and reference with $
Be sure to note however, your reactive object is a function call. So if the reactive object is data
and we want the list item normalized_df
we would call the reactive object data()
with ()
and then index into the list that function returns with $
. So all together we would have data()$normalized_df
.
data <- reactive({
req(input$filedata)
d <- read.csv(input$filedata$datapath, header = T)
list(data = d,
normalized_df = d + 1.5,
advanced_normalized = df + 1.5 * 45.454)
})
output$normalized_plot <- renderPlot({ #Does not work
plot(density(data()$normalizd_df[,1]), main = input$title)
})
output$advanced_normalized_plot <- renderPlot({
plot(density(data()$advanced_normalized[,1]), main = input$title)
})
Below is a minimal example that shows this in action:
library(shiny)
ui <- fluidPage(
titlePanel("Old Faithful Geyser Data"),
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 10,
value = 2)
),
mainPanel(
column(6, verbatimTextOutput("console1")),
column(6, verbatimTextOutput("console2"))
)
)
)
server <- function(input, output) {
data1 <- reactive({
datum <- mtcars
d1 <- mtcars[1:input$bins]
d2 <- d1 + 1
d3 <- d1 * 1.5
list(d1, d2, d3)
})
data2 <- reactive({
datum <- mtcars
list(d1 = mtcars[1:input$bins],
d2 = mtcars[1:input$bins] + 1,
d3 = mtcars[1:input$bins] * 1.5)
})
output$console1 <- renderPrint({
data1()
})
output$console2 <- renderPrint({
data2()
})
}
# Run the application
shinyApp(ui = ui, server = server)
Related Topics
How to Deal with Spaces in Column Names
Downloading Png from Shiny (R)
R: Extracting "Clean" Utf-8 Text from a Web Page Scraped with Rcurl
How to Facet a Plot_Ly() Chart
Plot Data Over Background Image with Ggplot
Convert Factor to Date/Time in R
R Shiny Table Not Rendering HTML
How to Detect Free Variable Names in R Functions
How to Generalize Outer to N Dimensions
Creating Multi Column Legend in Ggplot
Rbind Error: "Names Do Not Match Previous Names"
Adjust Plot Title (Main) Position
No Visible Global Function Definition for 'Median'