function assignment error in a vector(R language) - r

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)
}
}

Related

How to start debugger only when condition is met

Assume I have a function which uses a loop over integer i. Now something goes wrong and I assume the error happens when i=5. Now I can step through every single step (what I did up to now).
But now I read about the condition and text argument of browser and debug:
text a text string that can be retrieved when the browser is
entered.
condition a condition that can be retrieved when the browser
is entered.
Is it possible to use the arguments in a way it works as I want?
Here is an example. The debugger / browser should only start after i=5 is reached:
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
# browser(condition = (i == 5)) # does not work
result <- result + i * ( x + y)
}
return(result)
}
x <- 2
y <- 3
n <- 10
# debug(fun, condition = (i == 5)) # does not work
debug(fun)
r <- fun(x, y, n)
print(r)
The solution
if (i == 5) { # inside loop of fun()
browser()
}
is working, but I thougt there might be something better (No extra code inside the function)
You can use the argument expr in browser():
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
browser(expr = {i == 5})
result <- result + i * ( x + y)
}
return(result)
}
It will then only open the environment where browser() was called from if the expression evaluates to TRUE.
If you want to use debug():
debug(fun, condition = i == 5)
and then call the function:
fun <- function(x, y, n) {
result <- 0
for (i in 1:n) {
result <- result + i * ( x + y)
}
return(result)
}
fun(x, y, n)
Use advanced features of trace().
First, identify the line of your function to debug, following the help page instructions for the argument at =, leading to at = list(c(3, 4))
> as.list(body(fun))
[[1]]
`{`
[[2]]
result <- 0
[[3]]
for (i in 1:n) {
result <- result + i * (x + y)
}
[[4]]
return(result)
> as.list(body(fun)[[3]])
[[1]]
`for`
[[2]]
i
[[3]]
1:n
[[4]]
{
result <- result + i * (x + y)
}
Next, specify a conditional break point by providing as the tracer= argument an unevaluated expression that invokes the browser when a specific condition is met, tracer = quote(if (i == 3) browser())
So
> trace(fun, tracer = quote(if (i == 3) browser()), at=list(c(3, 4)), print=FALSE)
[1] "fun"
> r <- fun(x, y, n)
Called from: eval(expr, p)
Browse[1]>
debug: {
result <- result + i * (x + y)
}
Browse[2]> i
[1] 3
Browse[2]> result
[1] 15
Browse[2]>

How to add two functions to a new function in R

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)

Incrementing i when assigning functions?

I'm trying to create functions containing i in a loop, but i isn't been evaluated.
For example, the loop:
func <- list(0)
for (i in 1:3) {
func[[i]] <- function(x) i*x
}
produces:
> func[[1]]
function(x) i * x
<bytecode: 0x0000000011316b08>
when I actually need 1 * x, 2 * x, 3 * x
Write a function that returns a function. Be sure to use force() to force the evaluation of the lazy parameter.
func <- list(0)
makefun <- function(i) {
force(i)
function(x) i*x
}
func <- Map(makefun, 1:3)
func[[1]](5)
# [1] 5
func[[2]](5)
# [1] 10
func[[3]](5)
# [1] 15
You could do this in a for loop with the help of local().
func <- list(0)
for (i in 1:3) {
func[[i]] <- local({i<-i; function(x) i*x})
}
In both cases the definition still looks like "function(x) i*x" but the environment where the i value is coming from is different.
The issue is that your function refers to i, but there's only one i.MrFlick's answer is one way to force a local environment to be created to hold different copies of i with different values; another is to use local(), e.g.
func <- list()
for (i in 1:3) {
func[[i]] <- local(
{
j <- i # make a local copy of the current value
function(x) j*x
} )
}
func[[1]](5)
# [1] 5
func[[2]](5)
# [1] 10
func[[3]](5)
# [1] 15

for loop Warning message:numerical expression has 3 elements: only the first used

This is the warning message i am getting for the below code. Could some help figure out what could be the problem?
"Warning message:
In 1:x : numerical expression has 3 elements: only the first used"
x1 <- c(4,17,25)
sum_function <- function(x){
sum_fun <- 0
for(i in 1:length(x)) {
sum_fun <- sum_fun + i
}
return(sum_fun)
}
sum_function(x1)
If you wanted a sum of x1, you should have just written:
sum(x1) # or perhaps cumsum(x1) if cumulative sums were desired.
The second argument to the :-function should not be a multi-element vector, although your code above does not actually make that mistake. You can get that same warning message with:
x1 <- c(4,17,25)
junk_function <- function(x){
z <- 0
for(i in 1:x ) {
z <- z + i
}
}
junk_function(x1)
The warning was not coming from the for function but rather from the :-function. The correct version depending on what you assignment or goal was:
x1 <- c(4,17,25)
s_function <- function(x){
z <- 0
for( i in x ) {
z <- z + i
}
return(z)}
s_function(x1)

breaking out of for loop when running a function inside a for loop in R

Suppose you have the following function foo. When I'm running a for loop, I'd like it to skip the remainder of foo when foo initially returns the value of 0. However, break doesn't work when it's inside a function.
As it's currently written, I get an error message, no loop to break from, jumping to top level.
Any suggestions?
foo <- function(x) {
y <- x-2
if (y==0) {break} # how do I tell the for loop to skip this
z <- y + 100
z
}
for (i in 1:3) {
print(foo(i))
}
Admittedly my R knowledge is sparse and this is drycoded, but something like the following should work:
foo <- function(x) {
y <- x-2
if (y==0) {return(NULL)} # return NULL then check for it
z <- y + 100
z
}
for (i in 1:3) {
j <- foo(i)
if(is.null(j)) {break}
print(j)
}
Edit: updated null check for posterity
As a matter of coding practice, don't do this. Having a function that can only be used inside a particular loop is not a great idea. As a matter of educational interest, you can evaluate the 'break' in the parent environment.
foo <- function(x) {
y <- x-2
if (y==0) {eval.parent(parse(text="break"),1)}
z <- y + 100
z
}
for (i in 0:3) {
print(foo(i))
}
Are we allowed to be a little more creative? Could you recast your problem to take advantage of the following approach, where the operation is based on vectors?
x <- 1:3
y <- x[x-2 < 0] - 2 + 100 # I'm leaving the "- 2" separate to highlight the parallel to your code
y
If, however, a deeper form underlies the question and we need to follow this pattern for now, perhaps tweak it just a bit...
foo <- function(x) {
y <- x - 2
if (y != 0) {
z <- y + 100
z
} # else implicitly return value is NULL
}
for (i in 1:3) {
if (is.numeric(result <- foo(i))) {
print(result)
} else {
break
}
}
An alternative way is to throw an error and catch it with try, like so:
foo <- function(x) {
y <- x-2
if (y==0) {stop("y==0")}
z <- y + 100
z
}
try(for (i in 0:5) {
print(foo(i))
}, silent=TRUE)
## or use tryCatch:
for (i in 0:5) {
bar <- tryCatch(foo(i),error=function(e) NA)
if(is.na(bar)){ break } else { print(bar) }
}
I have no clue how r works but I found the question interesting because I could lookup a new language's syntax so excuse my answer if it is totally wrong :)
foo <- function(x) {
y <- x-2
if (y!=0) z <- NULL else z <- y + 100
z
}
for (i in 1:3)
{
a <- foo(i)
if (a == NULL) {next}
print(a)
}

Resources