I met a problem adding two functions together to a new function in R. For example, fun_1<-function(w)... fun_2<-function(w)... now I need to get a function fun(w)=fun_1(w)+fun_2(w) how could I do it?
Do you mean this ?
fun_1 <- function(x){
x ^ 2
}
fun_2 <- function(x){
x + 1
}
fun_3 <- function(x){
fun_1(x) + fun_2(x)
}
fun_3(1)
returns 3
k <- NA
fun <- function(w){
for (i in 1:100){
k[i] <- (-i/100)^2 + exp(w)
}
sum(k)
}
fun(1)
returns 305.6632
You can use get with envir = parent.frame() and just use paste to specify the function name.
# define functions
for(i in 1:100) assign(paste0('fun',i), function(w) (-i/100)^2+exp(w) )
# sum them
sum.fun <- function(x){
out <- 0
for(i in 1:100){
fun <- get(paste0('fun',i), envir = parent.frame())
out <- out + fun(x)
}
out
}
sum.fun(2)
Related
i need to find the number 35 in x and assign it a function.
Then call the function.
code:
x <- 1:100
z <- 0
z[x == 35] <- function() { # error here
print("hello")
}
z <- max(z, na.rm=TRUE) # remove all NA in vector
z() # run it
error:
Error in z[x == 35] <- function() { :
incompatible types (from closure to double) in subassignment type fix
Thanks!!
Quite why you'd want to do it, but...
x <- 1:100
z <- list()
z[[which(x == 35)]] <- function() {
print("hello")
}
z[[which(x == 35)]]() # run it
[1] "hello"
The key is to use a list, not a vector.
Do you mean something like this?
z <- function(x) {
print("hello")
max(x, na.rm=TRUE) # remove all NA in vector
}
for (x in 1:100){
if (x == 35){
z(x)
}
}
I am trying to run this example for the R Programming course on coursEra. However when I try to determine whether or not the matrix is square I get error saying "Error in is.square.matrix(x) : argument x is not a matrix"
My code is below:
library(matrixcalc)
##non-square matrix
NCols <- sample(3:6, 1)
NRows <- sample(2:8, 1)
myMat <- matrix(runif(NCols*NRows), ncol=NCols)
is.square.matrix(myMat)
## functions
makeMatrix <- function(x = matrix()) {
m <- NULL
set <- function(y) {
x <<- y
m <<- NULL
}
get <- function() x
setInv <- if (is.square.matrix(x) == TRUE) {
function(solve) m <<- solve
}
{
function(ginv) m <<- ginv
}
getInv <- function() m
list(x, set = set, get = get,
setInv = setInv,
getInv = getInv)
}
cacheMatrix <- function(x, ...) {
m <- x$getInv()
if(!is.null(m)) {
message("getting cached data")
return(m)
}
data <- x$get()
m <- if (is.square.matrix(x) == TRUE) {
solve(data, ...)
}
{
ginv(data, ...)
}
x$setInv(m)
m
}
## run functions for matrix
notSquare <- makeMatrix(myMat)
cacheMatrix(notSquare)
##check
ginv(myMat)
Then I get the error:
Error in is.square.matrix(x) : argument x is not a matrix
I am a beginner so not sure how to get the sentInv to recognize and check if the matrix is square or not.
Brian
Nevermind. In the makeMatrix function needed to replace x with (x = matrix()) and in the cacheMatrix replace x with (data)
Here's the answer. I just made the function (x) instead of function(x = matrix()) and 'data' is the variable to pull the matrix in the cache function need to have that me the input.
##non-square matrix
NCols <- sample(3:6, 1)
NRows <- sample(2:8, 1)
myMat <- matrix(runif(NCols*NRows), ncol=NCols)
is.square.matrix(myMat)
## functions
makeCacheMatrix <- function(x) {
m <- NULL
set <- function(y) {
x <<- y
m <<- NULL
}
get <- function() x
setInv <- if (is.square.matrix(x) == TRUE) {
function(solve) m <<- solve
}
else {
function(ginv) m <<- ginv
}
getInv <- function() m
list(x, set = set, get = get,
setInv = setInv,
getInv = getInv)
}
cacheSolve <- function(x, ...) {
m <- x$getInv()
if(!is.null(m)) {
message("getting cached data")
return(m)
}
data <- x$get()
m <- if (is.square.matrix(data) == TRUE) {
solve(data, ...)
}
else {
ginv(data, ...)
}
x$setInv(m)
m
}
## run functions for myMat
notSquare <- makeCacheMatrix(myMat)
cacheSolve(notSquare)
##check
ginv(myMat)
I would like to create a list of functions in R where values from a for loop are stored in the function definition. Here is an example:
init <- function(){
mod <- list()
for(i in 1:3){
mod[[length(mod) + 1]] <- function(x) sum(i + x)
}
return(mod)
}
mod <- init()
mod[[1]](2) # 5 - but I want 3
mod[[2]](2) # 5 - but I want 4
In the above example, regardless of which function I call, i is always the last value in the for loop sequence, I understand this is the correct behavior.
I'm looking for something that achieves this:
mod[[1]] <- function(x) sum(1 + x)
mod[[2]] <- function(x) sum(2 + x)
mod[[3]] <- function(x) sum(3 + x)
You can explicitly ensure i is evaluated at it's current value in the for loop by using force.
init <- function(){
mod <- list()
f_gen = function(i) {
force(i)
return(function(x) sum(i + x))
}
for(i in 1:3){
mod[[i]] <- f_gen(i)
}
return(mod)
}
mod <- init()
mod[[1]](2)
# [1] 3
mod[[2]](2)
# [1] 4
More details are in the Functions/Lazy Evaluation subsection of Advanced R. Also see ?force, of course. Your example is fairly similar to the examples given in ?force.
Using a single-function generator function (f_gen in my code above) seems to make more sense than a list-of-functions generator function. Using my f_gen your code code be simplified:
f_gen = function(i) {
force(i)
return(function(x) sum(i + x))
}
mod2 <- lapply(1:3, f_gen)
mod2[[1]](2)
# [1] 3
mod2[[2]](2)
# [1] 4
## or alternately
mod3 = list()
for (i in 1:3) mod3[[i]] <- f_gen(i)
mod3[[1]](2)
mod3[[2]](2)
Defining multiple functions in a loop:
par <- 1:2 #parameters for functions
qF <- list() #list I will write the functions into
for(i in 1:2){
qF[[i]] <- function(p){qnorm(p, mean = par[i])}
}
My result:
>qF
[[1]]
function (p)
{
qnorm(p, mean = par[i])
}
[[2]]
function (p)
{
qnorm(p, mean = par[i])
}
The functions are the same! What I WANT my result to be:
>qF
[[1]]
function (p)
{
qnorm(p, mean = par[1])
}
[[2]]
function (p)
{
qnorm(p, mean = par[2])
}
Is there any way to do this?
You can do:
library(functional)
funcs = lapply(1:2, function(u) Curry(qnorm, mean=u))
funcs[[1]](0.77)
#[1] 1.738847
funcs[[2]](0.77)
#[1] 2.738847
Or if you do not appreciate spicy meals:
funcs = lapply(1:2, function(u) function(...) qnorm(..., mean=u))
If you want to create the functions dynamically you need for the par[i] to evaluate each time, otherwise all the par[i] will be evaluated when the functions are called, and i will be the value at the end of the loop.
for(i in 1:2){
qF[[i]] <- local({
mu <- par[i]
function(...) { qnorm(..., mean = mu) }
})
}
You could also substitute the variable into the function body
for(i in 1:2){
qF[[i]] <- eval(substitute(
function(...) qnorm(..., mean = mu)), list(mu=par[i]))
}
And you can see what mu is in each function's environment
sapply(qF, function(f) mget("mu", environment(f)))
# $mu
# [1] 1
#
# $mu
# [1] 2
I'd like to perform this function on a matrix 100 times. How can I do this?
v = 1
m <- matrix(0,10,10)
rad <- function(x) {
idx <- sample(length(x), size=1)
flip = sample(0:1,1,rep=T)
if(flip == 1) {
x[idx] <- x[idx] + v
} else if(flip == 0) {
x[idx] <- x[idx] - v
return(x)
}
}
This is what I have so far but doesn't work.
for (i in 1:100) {
rad(m)
}
I also tried this, which seemed to work, but gave me an output of like 5226 rows for some reason. The output should just be a 10X10 matrix with changed values depending on the conditions of the function.
reps <- unlist(lapply(seq_len(100), function(x) rad(m)))
Ok I think I got it.
The return statement in your function is only inside a branch of an if statement, so it returns a matrix with a probability of ~50% while in the other cases it does not return anything; you should change the code function into this:
rad <- function(x) {
idx <- sample(length(x), size=1)
flip = sample(0:1,1,rep=T)
if(flip == 1) {
x[idx] <- x[idx] + v
} else if(flip == 0) {
x[idx] <- x[idx] - v
}
return(x)
}
Then you can do:
for (i in 1:n) {
m <- rad(m)
}
Note that this is semantically equal to:
for (i in 1:n) {
tmp <- rad(m) # return a modified verion of m (m is not changed yet)
# and put it into tmp
m <- tmp # set m equal to tmp, then in the next iteration we will
# start from a modified m
}
When you run rad(m) is not do changes on m.
Why?
It do a local copy of m matrix and work on it in the function. When function end it disappear.
Then you need to save what function return.
As #digEmAll write the right code is:
for (i in 1:100) {
m <- rad(m)
}
You don't need a loop here. The whole operation can be vectorized.
v <- 1
m <- matrix(0,10,10)
n <- 100 # number of random replacements
idx <- sample(length(m), n, replace = TRUE) # indices
flip <- sample(c(-1, 1), n, replace = TRUE) # subtract or add
newVal <- aggregate(v * flip ~ idx, FUN = sum) # calculate new values for indices
m[newVal[[1]]] <- m[newVal[[1]]] + newVal[[2]] # add new values