Nested IF function in R [duplicate] - r

This question already has an answer here:
R "Error: unexpected '}' in "}" [duplicate]
(1 answer)
Closed 5 years ago.
I am trying to build a function that takes 3 arguments, a vector, whether to display or not a graph, and if yes, the type of graph. Unfortunately, i get an error and don't understand why. (This is for a class but i already validated the points through reasoning, i just want to progress on my code...)
my_function <- function(x, display = FALSE, type) {
if (display = TRUE & type = "hist") {
hist(x)
} if (display = TRUE & type = "plot") {
plot(x)
} else {
summary(x)
}
}
I get multiples:
Error: unexpected '}' in " }"

You are using assignments in your if conditions instead of equality checks. In addition, you need to preface every if in a chain, other than the first one, with else. Try this code:
my_function <- function(x, display = FALSE, type) {
if (display == TRUE & type == "hist") {
hist(x)
} else if (display == TRUE & type == "plot") {
plot(x)
} else {
summary(x)
}
}

Related

if else Inside function for Further Execution in R

I want to generate a function with some conditions. If those conditions are TRUE then those will be used for further execution. But my problem is that R is not finding that even that is TRUE. Following is my R code;
require(KernSmooth)
require(kerdiest)
mini<-function(y,k,h1=TRUE, h2=TRUE, h3=TRUE,type){
n <- length(y)
x <- seq(min(y) + 0.05, max(y), length = k)
if(h1==TRUE){
h1 <- abs(dpik(y) )
} else { print("DPI is not selected")
}
if(h2==TRUE){
h2<-abs(ALbw(vec_data=y))
} else { print("AL is not selected")
}
if(h3==TRUE){
h3 <-abs(1.06*sd(y)*(n^(-1/5)))
} else { print("NSR is not selected")
}
ftrue<-switch(type,
Exp = dexp(x,(1/mean(x))),
Gamma = dgamma(x,(mean(x)/(var(x)/mean(x))),(var(x)/mean(x)))
)
dpi<-h1-sum(ftrue)
AL<-h2*3
nsr<-h3*4
v<-c("DPI"=dpi, "Altaman"=AL, "NSR"=nsr)
v[which.min(v)]
}#function end
y<-rexp(100,1)
mini(y,200,h1,h2,h3,"exp")
but there is error:
Error in mini(y, 200, h1, h2, h3, "exp") : object 'h1' not found
I am getting any clue what is my mistake here. Please help me in this problem.

Execute an Rscript until it has finished successfully [duplicate]

How can I simply tell R to retry a statement a few times if it errors? E.g. I was hoping to do something like:
tryCatch(dbGetQuery(...), # Query database
error = function(e) {
if (is.locking.error(e)) # If database is momentarily locked
retry(times = 3) # retry dbGetQuery(...) 3 more times
else {
# Handle other errors
}
}
)
I usually put the try block in a loop,
and exit the loop when it no longer fails or the maximum number of attempts is reached.
some_function_that_may_fail <- function() {
if( runif(1) < .5 ) stop()
return(1)
}
r <- NULL
attempt <- 1
while( is.null(r) && attempt <= 3 ) {
attempt <- attempt + 1
try(
r <- some_function_that_may_fail()
)
}
I wrote a quick function that allows you to easily retry an operating a configurable number of times, with a configurable wait between attempts:
library(futile.logger)
library(utils)
retry <- function(expr, isError=function(x) "try-error" %in% class(x), maxErrors=5, sleep=0) {
attempts = 0
retval = try(eval(expr))
while (isError(retval)) {
attempts = attempts + 1
if (attempts >= maxErrors) {
msg = sprintf("retry: too many retries [[%s]]", capture.output(str(retval)))
flog.fatal(msg)
stop(msg)
} else {
msg = sprintf("retry: error in attempt %i/%i [[%s]]", attempts, maxErrors,
capture.output(str(retval)))
flog.error(msg)
warning(msg)
}
if (sleep > 0) Sys.sleep(sleep)
retval = try(eval(expr))
}
return(retval)
}
So you can just write val = retry(func_that_might_fail(param1, param2), maxErrors=10, sleep=2) to retry calling that function with those parameters, give up after 10 errors, and sleep 2 seconds between attempts.
Also, you can redefine the meaning of what an error looks like by passing a different function as parameter isError, which by default will catch an error signaled with stop. This is useful if the function being called does something else on error, such as returning FALSE or NULL.
This is the alternative I've found so far that results in clearer, more readable code.
Hope this helps.
A solution without pre-assigning values and using for instead of while:
some_function_that_may_fail <- function(i) {
if( runif(1) < .5 ) stop()
return(i)
}
for(i in 1:10){
try({
r <- some_function_that_may_fail(i)
break #break/exit the for-loop
}, silent = FALSE)
}
r will be equal to the number of tries that were needed. If you dont want the output of the errors set silent to TRUE
Here's a function to generate a custom condition to respond to
locked <- function(message="occurred", ...) {
cond <- simpleCondition(message, ...)
class(cond) <- c("locked", class(cond))
cond
}
and a function implemented to allow (an infinite number of) restarts
f <- function() {
cnt <- 0L
repeat {
again <- FALSE
cnt <- cnt + 1L
withRestarts({
## do work here, and if needed...
signalCondition(locked())
}, retry=function() {
again <<- TRUE
})
if (!again) break
}
cnt
}
and the use of withCallingHandlers (to keep the context where the condition was signaled active unlike tryCatch) to handle the locked condition
withCallingHandlers({
n_tries <- 0L
f()
}, locked=function(e) {
n_tries <<- n_tries + 1L
if (n_retries < 3)
invokeRestart("retry")
})
I have put together the code and make it package: retry
f <- function(x) {
if (runif(1) < 0.9) {
stop("random error")
}
x + 1
}
# keep retring when there is a random error
retry::retry(f(1), when = "random error")
#> [1] 2
# keep retring until a requirement is satisified.
retry::retry(f(1), until = function(val, cnd) val == 2)
#> [1] 2
# or using one sided formula
retry::retry(f(1), until = ~ . == 2, max_tries = 10)
#> [1] 2
I like setting my object as an error from the start, also sometimes useful to add some sleep time if you're having connection problems:
res <- simpleError("Fake error to start")
counter <- 1
max_tries <- 10
# Sys.sleep(2*counter)
while(inherits(res, "error") & counter < max_tries) {
res <- tryCatch({ your_fun(...) },
error = function(e) e)
counter <- counter + 1
}

Unexpected bracket when using "if" inside function [duplicate]

This question already has answers here:
if/else constructs inside and outside functions
(2 answers)
Closed 5 years ago.
I constructed the function, but the R gives me the error. But I does not know what I did wrongly.
Error: unexpected '}' in "}"
Vect_fun=function(x,a) {
if(a=1)
{
y= mean(x,na.rm=TRUE)
}
else{
if(a=2)
{
y= na.aggregate(x)
}
else {
y=x[!is.na(x)]
}
}
y
}
Use double equal sign to comparing.
Vect_fun = function(x, a) {
if (a == 1) {
y = mean(x, na.rm = TRUE)
}
else {
if (a == 2) {
y = na.aggregate(x)
}
else {
y = x[!is.na(x)]
}
}
y
}
Your formatting is off in addition to needing to use the proper == operator, and else if
You should indent at each level so it's easier to read, and you need to use == for logical operators. Also, else{ if(){ }} is messy. Use else if{ }
Vect_fun <- function(x,a) {
if (a == 1) {
y = mean(x, na.rm = TRUE)
} else if (a == 2) {
y = na.aggregate(x)
return(y)
} else {
y = x[!is.na(x)]
}
return(y)
}

Error in R-function when input is string

I have made a function that tests which numbers in a range that are multiple of 6 and/or 3, or none of them.
Multi <- function(x,y) {
z = x:y
for (i in z) {
if (i%%1!=0 | i<0) {
print("Error!")
break
} else if (i%%3==0 & i%%6==0) {
print(paste(i, "is multiple of both 3 and 6"))
} else if (i%%3==0) {
print(paste(i, "is multiple of 3"))
} else {
print(paste(i, "is not multiple"))
}
}
}
The loop works as I want it to, but within the first if-statement, I would also like it to print "Error!" if a character/string is provided. The message I get when trying Multi("Hello",10) is:
Error in x:y : NA/NaN argument
In addition: Warning message:
In Multi("Hello", 10) : NAs introduced by coercion
I have tried the suppressWarnings() function, but I couldn't make it work.
Any suggestions?
Try this:
Multi <- function(x,y) {
if (!is.numeric(x) | !is.numeric(y)) {
print("Error!")
} else {
z = x:y
for (i in z) {
if (i%%1!=0 | i<0) {
print("Error!")
break
} else if (i%%3==0 & i%%6==0) {
print(paste(i, "is multiple of both 3 and 6"))
} else if (i%%3==0) {
print(paste(i, "is multiple of 3"))
} else {
print(paste(i, "is not multiple"))
}
}
}
}
Multi(1,10)
Multi('Hello', 10) # now it will print Error without a NaN: 'Hello':10 was causing this NaN
You can reduce the code a little bit also
sapply(1:10, function(i) ifelse(i%%3==0,
ifelse(i%%6==0,
paste(i, "is multiple of both 3 and 6"),
paste(i, "is multiple of 3")),
paste(i, "is not multiple")))

Checking if a returned number is an integer in GP/Pari?

This is my first time using GP/Pari and I am having trouble completing this question.
I am asked to print if the return of the function 'wq()' is an integer. Is there a function that can determine if the number passed in is an integer? If not how would I go about checking? I find the syntax somewhat difficult and can't find much information online about it.
I have included what I have so far, any help is appreciated.
wq(x) =
{
[(x-1)! + 1]/x
}
test(r,s) =
{
for (i=r, s, if(isinteger(wq(i)), print("integer"), print("not interger")));
}
If I understand correctly you want to check if (x-1)! + 1 is a multiple of x. You can do that with the modulo operation:
test(r,s) =
{
for (i=r, s, if(Mod((i - 1)! + 1, i) == 0,
print("integer"),
print("not integer")));
}
You can use:
wq(x) =
{
((x-1)! + 1)/x
}
test(r,s) =
{
for (i=r, s, print(if(type(wq(i))=="t_INT", "integer", "not integer")))
}
I changed [] into () since [] gives a row vector (type t_VEC) which is not useful here.
Here is another way to write it:
wq(x) =
{
Mod((x-1)! + 1, x)
}
test(r,s) =
{
for (i=r, s, wq(i) && print1("not "); print("integer"))
}
The function print1 prints and "stays" on the same line. The 'and' operator && "short-circuits". The semicolon ; binds several expressions into one "sequence".

Resources