modify variable within R function
There are ways as @Dason showed, but really - you shouldn't!
The whole paradigm of R is to "pass by value". @Rory just posted the normal way to handle it - just return the modified value...
Environments are typically the only objects that can be passed by reference in R.
But lately new objects called reference classes have been added to R (they use environments). They can modify their values (but in a controlled way). You might want to look into using them if you really feel the need...
Memory efficient way to modify a variable within a function
This question was already discussed here:
Pass an object to a function without copying it on change
Your second approach does not really solve the problem. Here is the test I ran with the results of mem_used()
library(pryr)
mem_used()
#41.3 MB
x <- matrix(1:1000000000, ncol=1000)
mem_used()
#4.04GB
f2<- function(x){
print(mem_used())
x = deparse(substitute(x))
print(mem_used())
x = get(x, envir = globalenv())
x<- x+1
print(mem_used())
x
}
x <- f2(x)
#4.04 GB
#4.04 GB
#12 GB
mem_used()
#8.04GB
R: modify variables defined in function
I'm sorry to say, that you've correctly identified using functions for your solution, but completely overstepped. But let's take the questions one-by-one:
Is there a way to access the variables defined inside foo?
No, this is by design that what's defined in a function stays within the function, and is only accessible from the function and its children (i.e., whatever the function itself is calling).
Is there a way to ... modify/overwrite the default values?
This is what function arguments are for, as you correctly deduced. But the solution is simpler; first, for the input variables:
foo <- function(var1 = 1, var2 = 3) {
var3 <- var1 + var2
var4 <- var3 * var2
return(c(var1, var2, var3, var4))
}
Note: Your return statement is very difficult to read, and potentially dangerous if you need, say, a 5th intermediate variable. It, too, will be returned, and you cannot guarantee the order of the returned variables.
If you need named variables, use a named vector:
return(c(v1=var1, s2=var2, var3=var3, m4=var4))
If your returned values are more complex than some scalar values, just use list
instead of the simple c
.
but what about the variables that are calculated based on other ones?
This is where it gets fun; there are several options depending on the complexity of what you want to do and how much flexibility the user should have. First, we can try to extend the above solution to include the computed values and only calculate them if not given:
foo <- function(var1 = 1, var2 = 3, var3, var4) {
if (missing(var3))
var3 <- var1 + var2
if (missing(var4))
var4 <- var3 * var2
return(c(var1, var2, var3, var4))
}
The function missing
simply tells you, if the argument var3
was provided. R is a bit funny here as in other languages, function arguments without defaults must be given when calling the function. R doesn't play like that and will only require the variable if you ask for it.
But, if var3
and var4
are simple calculations, couldn't they just be defined in the function signature?
foo <- function(var1 = 1, var2 = 3, var3 = var1 + var2, var4 = var3 * var2) {
return(c(var1, var2, var3, var4))
}
Turns out it works in this case but don't do it!. It will not work for more complex data types (lists, data frames) and it is bad coding style, because it also makes the function less readable.
R function wont modify global variable
I think I know what is wrong
Change data <- table
to data <<- table
within your function
You are assigning the result to the local environment for the function, whilst the <<-
will be assigning it to the global environment.
I would propose you try the following
library(rvest)
getData <- function(url) { html_table(read_html(url)) }
data <- getData("https://steemdb.com/accounts/reputation?page=1")
Or even better
library(rvest)
getData <- function(url) { html_table(read_html(url)) }
steemdb.url <-"https://steemdb.com/accounts/reputation?page="
data <- lapply(1:100, function(i) getData(paste0(steemdb.url, i)) )
data <- do.call(rbind, data)
View(data)
1:100 will get you the first 100 pages.
write r function to modify value in data frame
If we are passing column name as string, then use [[
instead of $
and return
the dataset
MakeBinary <- function(varName, dfName){
dfName[[varName]][dfName[[varName]] >= 1] <- 1
dfName
}
MakeBinary("Var2", df)
example with mtcars
MakeBinary("carb", head(mtcars))
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 1
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 1
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 1
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Unquoted arguments for variable names can be passed as well, but it needs to be converted to string
MakeBinary <- function(varName, dfName){
varName <- deparse(substitute(varName))
dfName[[varName]][dfName[[varName]] >= 1] <- 1
dfName
}
MakeBinary(Var2, df)
Using a reproducible example with mtcars
MakeBinary(carb, head(mtcars))
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 1
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 1
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 1
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
Can non-global variables be modified inside a function in R?
It is possible to update a global variable, in a function using get
and assign
function. Below is the code, which does the same :
heatmap.matrix <- matrix(rep(0,40000), nrow=200, ncol=200)
# foo function should just update a single cell of the declared matrix
varName <- "heatmap.matrix"
foo <- function() {
heatmap.matrix.copy <- get(varName)
heatmap.matrix.copy[40,40] <- 100
assign(varName, heatmap.matrix.copy, pos=1)
}
heatmap.matrix[40,40]
#[1] 0
foo()
heatmap.matrix[40,40]
# [1] 100
you should read up a bit on environments concept. The best place to start is http://adv-r.had.co.nz/Environments.html
How can I change variable value in R apply function?
It is because variable assignment within a function is lost when the function terminates. As Zheyuan Li rightly pointed out, assigning to the global environment gets around this as this way the assignment is not lost upon termination.
I prefer using the assign()
function as you can explicitly determine where the variable is stored (not always the case with <<-
).
idx=1
f <- function(x){
assign('idx', idx+1, envir = globalenv())
print(c("current progress", idx))
return(1)
}
res=sapply(1:3,f)
Related Topics
Building a Tiny R Package with Cuda and Rcpp
How to Get Xtabs to Calculate Means Instead of Sums in R
Error When Using Predict() on a Randomforest Object Trained with Caret's Train() Using Formula
Keep Document Id with R Corpus
Digging into R Profiling Information
In R, Evaluate Expressions Within Vector of Strings
Count Consecutive Numbers in a Vector
Range Join Data.Frames - Specific Date Column with Date Ranges/Intervals in R
Match and Replace Multiple Strings in a Vector of Text Without Looping in R
How to Extend '==' Behavior to Vectors That Include Nas
Cumulative Sum for Positive Numbers Only
R Remove Parts of Column Name After Certain Characters
Pass String to Facet_Grid:Ggplot2
How to Get Axis Ticks Labels with Different Colors Within a Single Axis for a Ggplot Graph
Automated Ggplot2 Example Gallery in Knitr
Sort Matrix According to First Column in R
How to Generate a Frequency Table in R with With Cumulative Frequency and Relative Frequency