Global variables in R
As Christian's answer with assign()
shows, there is a way to assign in the global environment. A simpler, shorter (but not better ... stick with assign) way is to use the <<-
operator, ie
a <<- "new"
inside the function.
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)
Global and local variables in R
Variables declared inside a function are local to that function. For instance:
foo <- function() {
bar <- 1
}
foo()
bar
gives the following error: Error: object 'bar' not found
.
If you want to make bar
a global variable, you should do:
foo <- function() {
bar <<- 1
}
foo()
bar
In this case bar
is accessible from outside the function.
However, unlike C, C++ or many other languages, brackets do not determine the scope of variables. For instance, in the following code snippet:
if (x > 10) {
y <- 0
}
else {
y <- 1
}
y
remains accessible after the if-else
statement.
As you well say, you can also create nested environments. You can have a look at these two links for understanding how to use them:
- http://stat.ethz.ch/R-manual/R-devel/library/base/html/environment.html
- http://stat.ethz.ch/R-manual/R-devel/library/base/html/get.html
Here you have a small example:
test.env <- new.env()
assign('var', 100, envir=test.env)
# or simply
test.env$var <- 100
get('var') # var cannot be found since it is not defined in this environment
get('var', envir=test.env) # now it can be found
Output selected variables to global environment R function
It is not recommended to write to global environment from inside the function. If you want to create multiple objects in the global environment return a named list from the function and use list2env
.
mediansFunction <- function(x){
labmedians <- sapply(x[-1], median)
median_of_median <- median(labmedians)
grand_median <- median(as.matrix(x[-1]))
labMscore <- as.vector(round(abs(scores_na(labmedians, "mad")), digits = 2)) #calculate mscore by lab
labMscoreIndex <- which(labMscore > MscoreMax) #get the position in the vector that exceeds Mscoremax
x[-1][labMscoreIndex] <- NA # discharge values above threshold by making NA
dplyr::lst(data = x, labmedians, grand_median, labMscore)
}
result <- mediansFunction(df)
list2env(result, .GlobalEnv)
Now you have variables data
, labmedians
, grand_median
and labMscore
in the global environment.
Unit testing functions with global variables in R
I think you misunderstand what utils::globalVariables("COUNTS")
does. It just declares that COUNTS
is a global variable, so when the code analysis sees
addx <- function(x) {
COUNTS + x
}
it won't complain about the use of an undefined variable. However, it is up to you to actually create the variable, for example by an explicit
COUNTS <- 0
somewhere in your source. I think if you do that, you won't even need the utils::globalVariables("COUNTS")
call, because the code analysis will see the global definition.
Where you would need it is when you're doing some nonstandard evaluation, so that it's not obvious where a variable comes from. Then you declare it as a global, and the code analysis won't worry about it. For example, you might get a warning about
subset(df, Col1 < 0)
because it appears to use a global variable named Col1
, but of course that's fine, because the subset()
function evaluates in a non-standard way, letting you include column names without writing df$Col
.
Using global variable in function
Both <<-
and assign
will work:
myfunction <- function(var1, var2) {
# Modification of global mydata
mydata <<- ...
# Alternatively:
#assign('mydata', ..., globalenv())
# Assign locally as well
mydata <- mydata
# Definition of another variable with the new mydata
var3 <- ...
# Recursive function
mydata = myfunction(var2, var3)
}
That said, it’s almost always a bad idea to want to modify global data from a function, and there’s almost certainly a more elegant solution to this.
Furthermore, note that <<-
is actually not the same as assigning to a variable in globalenv()
, rather, it assigns to a variable in the parent scope, whatever that may be. For functions defined in the global environment, it’s the global environment. For functions defined elsewhere, it’s not the global environment.
store variables from a function in the global environment
You could use assign
:
assign("v","hi",envir = globalenv())
This requires that you have the name of the target global variable as a string, but it can be easy to do this even with a vector of dozens of such things.
This question discusses the differences between assign
and <<-
. The chief difference is that assign
lets you specify the environment -- so it is easy to use it to store data in a non-global but persistent environment so that you could e.g. emulate static variables in R. While it is possible to use assign
to modify the global environment, you should be aware that it is seldom a good thing to do so. There is too much of a danger of accidentally overwriting data that you don't want to have overwritten. Code which makes heavy use of global variables can almost always be refactored into cleaner code which doesn't. If you need to get a lot of heterogeneous data from a function to the calling environment, the cleanest solution would be to return the needed data in a list.
The accepted answer ends its discussion of <<-
and assign
with a good quote:
The Evil and Wrong use is to modify variables in the global
environment.
Related Topics
Method to Extract Stat_Smooth Line Fit
Capitalize the First Letter of Both Words in a Two Word String
How to Merge 2 Vectors Alternating Indexes
R Spreading Multiple Columns With Tidyr
Overlay Histogram With Density Curve
Create Sequence of Repeated Values, in Sequence
Subset Rows in a Data Frame Based on a Vector of Values
How to Put Labels Over Geom_Bar For Each Bar in R With Ggplot2
How to Delete Rows from a Dataframe That Contain N*Na
How to Efficiently Calculate Distance Between Pair of Coordinates Using Data.Table :=
Change Bar Plot Colour in Geom_Bar With Ggplot2 in R
Subsetting R Data Frame Results in Mysterious Na Rows
Dplyr Join on By=(A = B), Where a and B Are Variables Containing Strings
Read a Text File in R Line by Line
How to Load Packages in R Automatically
Using Unicode 'Dingbat-Like' Glyphs in R Graphics, Across Devices & Platforms, Especially Pdf