Can ellipsis be iterated in R like *args in Python? - r

The newly-defined function to sum inputs:
mysum=function(...){
return(sum(...))
invisible(...)
}
> mysum(1,2,3,4)
[1] 10
What if I don't use the sum function?I mean this:
mysum=function(...){
s=0
for(i in ...){
s=s+i
}
return(s)
}
It doesn't work. Can ... be iterated?
In Python,it's simple:
def mysum(*args):
s=0
for i in args:
s+=i
return(s)

use c() on ellipsis before the loop, and assign it inside the function:
mysum=function(...){
vec = c(...)
s=0
for(i in vec){
s=s+i
}
return(s)
}
mysum(1,2,3)
[1] 6

Yes!
The usual route is to stuff it into a list and then iterate over the list:
my_fun <- function(...) {
args <- list(...)
# do stuff with ellipses args.
}
Whether you use lapply, go straight for named arguments or just loop over (for (i in seq_along(args)) {args[[i]]}) is up to you.
If you assume ... only contains vectors, you could do:
args <- unlist(list(...))
sum(args)

Related

Putting user-defined on a list in for loop

I have problems storing user defined functions in R list when they are put on it in a for loop.
I have to define some segment-specific functions based on some parameters, so I create functions and put them on a list looping through segments with for-loop. The problem is I get same function everywhere on a result list.
The code looks like this:
n <- 100
segmenty <- 1:n
segment_functions <- list()
for (i in segmenty){
segment_functions[[i]] <- function(){return(i)}
}
When i run the code what I get is the same function (last created in the loop) for all indexes:
## for all k
segment_functions[[k]]()
[1] 100
There is no problem when I put the functions on list manually e.g.
segment_functions[[1]] <- function(){return(1)}
segment_functions[[2]] <- function(){return(2)}
segment_functions[[3]] <- function(){return(3)}
works just fine.
I honsetly have no idea what's wrong. Could you help?
You need to use the force function to ensure that the evaluation of i is done during the assignment into the list:
n <- 100
segmenty <- 1:n
segment_functions <- list()
f <- function(i) { force(i); function() return(i) }
for (i in segmenty){
segment_functions[[i]] <- f(i)
}
I'd use lapply and capture i in a clousre of the wrapper:
segment_functions <- lapply(1:100, function(i) function() i)

Relooping a function over its own output

I have defined a function which I want to reapply to its own output multiple times. I tried
replicate(1000,myfunction)
but realised that this is just applying my function to my initial input 1000 times, rather than applying my function to the new output each time. In effect what I desire is:
function(function(...function(x_0)...))
1000 times over and being able to see the changes at each stage.
I have previous defined b as a certain vector of length 7.
b_0=b
C=matrix(0,7,1000)
for(k in 1:1000){
b_k=myfun(b_(k-1))
}
C=rbind(b_k)
C
Is this the right idea behind what I want?
You could use Reduce for this. For example
add_two <- function(a) a+2
ignore_current <- function(f) function(a,b) f(a)
Reduce(ignore_current(add_two), 1:10, init=4)
# 24
Normally Reduce expects to iterate over a set of new values, but in this case I use ignore_current to drop the sequence value (1:10) so that parameter is just used to control the number of times we repeat the process. This is the same as
add_two(add_two(add_two(add_two(add_two(add_two(add_two(add_two(add_two(add_two(4))))))))))
Pure functional programming approach, use Compose from functional package:
library(functional)
f = Reduce(Compose, replicate(100, function(x) x+2))
#> f(2)
#[1] 202
But this solution does not work for too big n ! Very interesting.
A loop would work just fine here.
apply_fun_n_times <- function(input, fun, n){
for(i in 1:n){
input <- fun(input)
}
return(input)
}
addone <- function(x){x+1}
apply_fun_n_times(1, addone, 3)
which gives
> apply_fun_n_times(1, addone, 3)
[1] 4
you can try a recursive function:
rec_func <- function(input, i=1000) {
if (i == 0) {
return(input)
} else {
input <- myfunc(input)
i <- i - 1
rec_func(input, i)
}
}
example
myfunc <- function(item) {item + 1}
> rec_func(1, i=1000)
[1] 1001

How to simplify sub functions' arguments in R?

Suppose I have a function with sub functions like this format:
f<-function(f,a,b,c,d,e) {
f1<-function(a,b,c,d,e){
cbind(rnorm(a,mean=b,sd=1),
rnorm(a,mean=b,sd=c),
rbinom(a,d,e))
}
out<-list()
for(i in 1:f) {out[[i]]<-f1(a,b,c,d,e)}
return(out)
}
f(a=10,b=3,c=4,d=3,e=0.5,f=6)
Q1:
How to simplify the arguments for f1?
Q2:
I use list() and for loop for the out, How to rbind() or other better ways to return a single data frame?
Q3:
How to add ... in the f( ) to pass arguments for function mean, rnorm and rbinom?
func1, func2 and func3 can already access the arguments of func directly so it is unnecessary pass the arguments of func to each of them. e.g.
f <- function(x) {
g <- function() x*x
g()
}
f(2)
use as.list(environment()) eg
not.include <- c("a", "f", "vars", "not.include")
vars <- as.list(environment())
vars[! names(vars) %in% not.include]
do.call(func1, vars)

Get the names of list variables when provided as function parameters

Lets say I have a function that accepts variables that are always part of a list.
myfun <- function(x$name,y$name) {
# stuff
}
What I'd like to do is get the names used.
alist <- list(Hello=1,Goodbye=2)
myfun(alist$Hello, alist$Goodbye) {
# I want to be able to work with the characters "Hello" and "Goodby" in here
}
So, within my function, how would I get the characters "Hello" and "Goodbye". Given alist$Hello and alist$Goodbye
I recall that plot.default does this with deparse(substitute(:
a <- list(a="hello",b=c(1,2,3))
f <- function(x,y) { print(deparse(substitute(x))); print(deparse(substitute(y))) }
f(a$a,a$b)
#[1] "a$a"
#[1] "a$b"
Something like this, perhaps:
myfun <- function(x) { print(substitute(x))}
myfun(iris$Sepal.Length)
## iris$Sepal.Length
I'd create the function with a list argument:
myfun <- function(l) {
print(names(alist))
}
myfun(alist)
# [1] "Hello" "Goodbye"

How can I expand a vector into the arguments of a function in r?

If I have the function with three individual arguments
fun <- function(a,b,c){
a+b^2*c
}
How can I call it using a single vector
my_vector <- c(1,2,3)
fun(my_vector)
try this:
> do.call("fun", as.list(my_vector))
[1] 13
This should work!
fun(1,2,3)
Otherwise,
fun <- function(x){
x[1]+x[2]^2*x[3]
}
fun(c(1,2,3))

Resources