R: How to Create a Vector of Functions

How to create a vector of functions?

Use a factory function with a closure over its argument (which will hold the value of the looping variable):

> # the factory function
> makefunc <- function(x) { x; function() x }
> funclist <- list()
> for (i in 1:3) funclist[[i]] <- makefunc(i)
> funclist[[1]]()
[1] 1
> funclist[[2]]()
[1] 2
>

R: How to create a vector of functions?

This can be solved using an eval-parse construct, although I strongly advice you not to use this construct. It often causes more problems than anything else. But I couldn't get a decent do.call way of doing it.

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
eval(parse(text=paste("function(number) func(number=number, coefficient=",i,")"))))
}

Reason is as Aaron explained: everything within the function definition is taken as is until the function evaluation.

Small remark: this is especially a list of functions, and not a vector. It's impossible to have a vector of type "function". It's also absolutely useless, as you have to select the function using the index [[]] before you can use it. Then I'd just add the argument instead of defining a function for every possible value of one of the arguments.

So what you want to achieve is unclear, but if you want to apply func with different coefficients, I wonder why you don't simply do:

> x <- c(10,20,30)
> sapply(1:4,function(y)func(number=x,coefficient=y))
[,1] [,2] [,3] [,4]
[1,] 10 20 30 40
[2,] 20 40 60 80
[3,] 30 60 90 120

A variation on the theme by Marek (avoiding the parsing):

vector_of_functions = NULL
for (i in 1:4) {
vector_of_functions = c(vector_of_functions,
eval(substitute(function(number) func(number=number, coefficient=i),list(i=i))))
}

The 1L etc. you get, just indicate they're exact integers (that take less memory space).

How do I define a list/vector of functions in R?

If you want to have a list of functions, you can do something like:

myFuns <- list(mean, sd)

And then you can lapply over this list, or use the for loop as you wanted. If you use the for loop make sure that you use the [[ syntax, because this makes sure that you are retrieving the function and not a length one list:

for (i in 1:n){
output[i] <- WrapperFunction(x, myFuns[[i]])
}

or

lapply(myFuns, WrapperFunction, x = x)

R: Writing a function which has as its input a vector

Perhaps:

 x [ mapply( function(xx,yy) {isTRUE(all.equal(xx,yy))}, 
xx=(x) ^ (1/3) ,
yy=round( (x) ^ (1/3), 0 ) ) ]

> x <- 1:512 # to get your desired range it would be `seq.int(500000000)`
> x[ mapply( function(xx,yy) {isTRUE(all.equal(xx,yy))},
xx=(x) ^ (1/3) ,
yy=round( (x) ^ (1/3), 0 ) ) ]
[1] 1 8 27 64 125 216 343 512

I think that 500 000 000 is below integer.max or max.integer. You should check .Machine

(This is going to be slow. Better algorithms are possible and perhaps that is perhaps what your instructor wants.)

> x <- seq.int(50000)
> cubes
[1] 1 8 27 64 125 216 343 512 729 1000 1331 1728 2197 2744 3375
[16] 4096 4913
> cubes <- x[ mapply( function(xx,yy) {isTRUE(all.equal(xx,yy))}, xx=(x) ^ (1/3) , yy=round( (x) ^ (1/3), 0 ) ) ]
> cubes
[1] 1 8 27 64 125 216 343 512 729 1000 1331 1728
[13] 2197 2744 3375 4096 4913 5832 6859 8000 9261 10648 12167 13824
[25] 15625 17576 19683 21952 24389 27000 29791 32768 35937 39304 42875 46656

I suspect this is linear in length of x

> x <- seq.int(500000)
> system.time( {cubes <- x[ mapply( function(xx,yy) {isTRUE(all.equal(xx,yy))}, xx=(x) ^ (1/3) , yy=round( (x) ^ (1/3), 0 ) ) ] } )
user system elapsed
105.455 1.110 107.138

This only require checking a relatively few values, since cube-root of your max is only 793 plus a fraction:

x[ x %in% (1:(max(x)^(1/3)) )^3]   # almost instantaneous with x <- 1:500000
# ==== testing worst case scenario ====
> x <- 1:500000000
> system.time( {cubes <- x[ x %in% (1:(max(x)^(1/3)) )^3]})
user system elapsed
25.025 8.379 32.857 # that's in seconds

Create a vector function from a scalar function in R

You would have to Vectorize the function f to get it to apply over a vector:

f = Vectorize(f)
print(f(bins))

Note that you could have also just used curve with sapply:

curve(sapply(x, f), from=-5, to=5)

Finally, if you wrote the function with ifelse like so:

f = function(x) {
ifelse(x >= -5 & x <= -3, 3*(1-(x+4)^2)/8, ifelse(x>=3 & x<=5, 3*(1-(x-4)^2)/8, 0))
}

That would allow it to work on vectors without needing Vectorize.

Create a list of functions from a vector of characters

Maybe initialize your list with a single generic function, and then update them using:

foo <- function(x){x+3}
> body(foo) <- quote(x+4)
> foo
function (x)
x + 4

More specifically, starting from a character, you'd probably do something like:

body(foo) <- parse(text = "x+5")

How to create a vector with character string and corresponding number for each repeat

Use paste or paste0. The second argument is vectorized, so it'll give you the full vector.

paste("user", 1:33, sep = "_")
paste0("user_", 1:33)

output

 [1] "user_1"  "user_2"  "user_3"  "user_4"  "user_5"  "user_6"  "user_7"  "user_8" 
[9] "user_9" "user_10" "user_11" "user_12" "user_13" "user_14" "user_15" "user_16"
[17] "user_17" "user_18" "user_19" "user_20" "user_21" "user_22" "user_23" "user_24"
[25] "user_25" "user_26" "user_27" "user_28" "user_29" "user_30" "user_31" "user_32"
[33] "user_33"

R - How to create a function with numeric vectors as arguments

You've very nearly solved your own problem by recognizing that na.rm is an argument that controls how missing values are treated. Now you just need to apply this knowledge to both min and max.

The benefit of functions is that you can pass your arguments to other functions, just as you have passed v. The following will define what you wish:

minmax <- function(v, noNA = TRUE){
max(v, na.rm = noNA) - min(v, na.rm = noNA)
}

I would recommend, however, that you use an argument name that is familiar

minmax <- function(v, na.rm = TRUE){
max(v, na.rm = na.rm) - min(v, na.rm = na.rm)
}

As pointed out earlier, you may be able to simplify your code slightly by using

minmax <- function(v, na.rm = TRUE){
diff(range(v, na.rm = na.rm))
}

Lastly, I would suggest that you don't use T in place of TRUE. T is a variable that can be reassigned, so it isn't always guaranteed to be TRUE. TRUE, on the other hand, is a reserved word, and cannot be reassigned. Thus, it is a safer logical value to use.



Related Topics



Leave a reply



Submit