I am new to R. So basically I have 2 questions:
In C++ we can pass objects as references to be able to return multiple modified objects from a function. What is equivalent way to modify multiple objects inside a function? (for example, a and b in fyfunc)
In below code, I thought since I have access to b inside myfunc, I could modify it. But apparently, it's a copy of b. Is there anyway to actually modify b inside myfunc?
a <- c(1,2,3)
b <- c(4,5,6)
myfunc <- function(a) {
b <- b+1
cat(b) # prints: 5 6 7
a <- a+1
}
a <- myfunc(a)
a
b # stil 4 5 6
you can use <<- instead of <- or assign('b', b+1, envir = globalenv()) in function myf.
myf <- function(a) {
assign('b', b+1, envir = globalenv())
cat(b) # prints: 5 6 7
a <- a+1
}
Related
I have a list
l <- list('a','b','c')
That I want to use iteratively to create object names in a function. For example:
f <- function(){
object <- 1 + 2
}
I wanted to run the operation a+b multiple times and each time create a new object with each time naming an object based on something on my list. Is there a way to use a list to iteratively name an object?
I hope this question makes sense...
EDIT:
I am hoping that my output would give me 3 objects:
a, b, and c. Each of these would equal 3 based on the function.
Not sure what the overall goal is but here's a way to do that :
f <- function(){
object <- p + q
}
p <- 10
q <- 5
list2env(setNames(replicate(length(l), f(), simplify = FALSE), l), .GlobalEnv)
a
#[1] 15
b
#[1] 15
c
#[1] 15
a <- 10
f <- function(){
a <<- 3
function() {
a <<- 15
a <- 5
return(a)
}
}
g <- f()
g()
a
When I run the above code I get the following output:
5
15
Can someone please explain how the second output is 15 instead of 3? And the same code returns 10 for a when I do not use "<<-" in the function f.
Just see what your function f returns.
f()
function() {
a <<- 15
a <- 5
return(a)
}
<environment: 0x000000001f1c7898>
So when you assign this result, a function, to g it becomes that function in the output above. The code line a <<- 3 is never executed when you call g.
In other words, the second output is explained in the same fashion the first output is explained, g sets the variable a that exists in the globalenv to 15 and returns a value of variable a <- 5 created in its own environment.
EDIT.
Note that if, like Dason says in his comment, print a before calling g its value has changed to 3 like you expect it in your question. The code line a <<- 3 was indeed executed when f was called.
g <- f() # call 'f'
a # print 'a', the value has changed
[1] 3
g() # now call 'g'
[1] 5
a # and the value of 'a' changed again
[1] 15
I have a global variable x and want to build a function f that returns the value of x at the time the function is created. Example:
x <- 5
f <- function() return(x)
f()
> 5
x <- 10
f()
> 10 # Should return 5
I want a function that always return 5 (or whatever the value of x is at the time of function creation) without using another global variable. Is that possible?
Still another option using body:
f<-`body<-`(function() {},value=x)
Example:
x<-10
f<-`body<-`(function() {},value=x)
f()
#[1] 10
x<-100
f()
#[1] 10
Digging the source code of body, here is an even cleaner solution equivalent to the above using as.function:
f<-as.function(list(x))
This is not possible with global variables alone. When a function is defined, none of the variables in the function body are actually evaluated till the function is called. What you want seems to be a closure to hold the value at the time of creation. Instead write a function that returns a function
x <- 5
getfun <- function() {z<-x; function() return(z)}
f <- getfun()
x<- 10
g <- getfun()
f()
# [1] 5
g()
# [1] 10
Or even better, don't implicitly use global variables. Create a function that takes a certain set of parameters and returns a new function
returnVal <- function(x) {force(x); function() return(x)}
f<-returnVal(5)
g<-returnVal(10)
f()
# [1] 5
g()
# [1] 10
1) This saves the value of x the first time f is called and then uses that value of x even if x has been changed the next time f is called. Create f in a local environment and have f place x in that environment. If x was not previously there it will now be. If it was previously there then it will be the x retrieved and placed back. The result is that the first x encountered will always be used.
f <- local(function() {
p <- parent.env(environment())
p$x <- x
x
})
x <- 5
f()
## [1] 5
x <- 10
f()
## [1] 5
2) In comments #Konrad and #Frank have suggested the following variation in which we remove the assignment from f and put it in the local.
There is one difference from the viewpoint of the user of the function. This instantiates the value of x at the time the function is defined whereas (1) instantiates x the first time that the function is called and that might be an advantage if you want to separate the definition and the instantiation.
x <- 5
f <- local({ x <- x; function() x })
f()
## [1] 5
x <- 10
f()
## [1] 5
3) We can also consider completely separating the function from the instantiation. This would also allow re-initialization at any time by calling e$init() again.
e <- local({
init <- function() {
p <- parent.env(environment())
p$x <- x
}
run = function() x
environment()
})
x <- 5
e$init()
e$run()
## [1] 5
x <- 10
e$run()
## [1] 5
4) (3) could be implemented using a variety of object oriented frameworks such as Reference Classes, proto or R6. In proto it would be like this:
library(proto)
p <- proto(init = function(.) .$x <- x, run = function(.) x)
x <- 5
p$init()
p$run()
## [1] 5
x <- 10
p$run()
## [1] 5
I want to create a string in a loop and use this string as object in this loop. Here is a simplified example:
for (i in 1:2) {
x <- paste("varname",i, sep="")
x <- value
}
the loop should create varname1, varname2. Then I want to use varname1, varname2 as objects to assign values. I tried paste(), print() etc.
Thanks for help!
You could create the call() to <- and then evaluate it. Here's an example,
value <- 1:5
for (i in 1:2) {
x <- paste("varname",i, sep="")
eval(call("<-", as.name(x), value))
}
which creates the two objects varname1 and varname2
varname1
# [1] 1 2 3 4 5
varname2
# [1] 1 2 3 4 5
But you should really try to avoid assigning to the global environment from with in a method/function. We could use a list along with substitute() and then we have the new variables together in the same place.
f <- function(aa, bb) {
eval(substitute(a <- b, list(a = as.name(aa), b = bb)))
}
Map(f, paste0("varname", 1:2), list(1:3, 3:6))
# $varname1
# [1] 1 2 3
#
# $varname2
# [1] 3 4 5 6
assign("variableName", 5)
would do that.
For example if you have variable names in array of strings you can set them in loop as:
assign(varname[1], 2 + 2)
More and more information
https://stat.ethz.ch/R-manual/R-patched/library/base/html/assign.html
#MahmutAliĆZKURAN has answered your question about how to do this using a loop. A more "R-ish" way to accomplish this might be:
mapply(assign, <vector of variable names>, <vector of values>,
MoreArgs = list(envir = .GlobalEnv))
Or, as in the case you specified above:
mapply(assign, paste0("varname", 1:2), <vector of values>,
MoreArgs = list(envir = .GlobalEnv))
I had the same issue and for some reason my apply's weren't working (lapply, assign directly, or my preferred goto, mclapply)
But this worked
vectorXTS <- mclapply(symbolstring,function(x)
{
df <- symbol_data_set[symbol_data_set$Symbol==x,]
return(xts(as.data.frame(df[,-1:-2]),order.by=as.POSIXct(df$Date)))
})
names(symbolstring) <- symbolstring
names(vectorXTS) <- symbolstring
for(i in symbolstring) assign(symbolstring[i],vectorXTS[i])
Inside a function I define a bunch of scalar variables like this:
a <- 10
b <- a*100
c <- a + b
At the end of the function, I want to return a,b,c in a named vector, with the same names as the variables, with minimal coding, i.e. I do not want to do:
c( a = a, b = b, c = c )
Is there a language construct that does this? For example, if I simply do return(c(a,b,c)) it returns an unnamed vector, which is not what I want. I currently have a hacky way of doing this:
> cbind(a,b,c)[1,]
a b c
10 1000 1010
Is there perhaps a better, less hacky, way?
Here's a function to do that for you, which also allows you to optionally name some of the values. There's not much to it, except for the trick to get the unevaluated expression and deparse it into a single character vector.
c2 <- function(...) {
vals <- c(...)
if (is.null(names(vals))) {
missing_names <- rep(TRUE, length(vals))
} else {
missing_names <- names(vals) == ""
}
if (any(missing_names)) {
names <- vapply(substitute(list(...))[-1], deparse, character(1))
names(vals)[missing_names] <- names[missing_names]
}
vals
}
a <- 1
b <- 2
c <- 3
c2(a, b, d = c)
# a b d
# 1 2 3
Note that it's not guaranteed to produce syntactically valid names. If you want that, apply the make.names function to the names vector.
c2(mean(a,b,c))
# mean(a, b, c)
# 1
Also, as with any function that uses substitute, c2 is more suited for interactive use than to be used within another function.