Dynamically rendered condition for an if loop in R - r

I am trying to create a condition for an if-loop which is not predefined. The "length" of the condition is depending of the length of my List
where prior calculated values are stored.
The proceed you can see in my code down below.
I tried to convert my character condition with some functions (expression(), eval() ...) so that the condition is readable for the if loop. But nothing works...
So I hope you can help me solving my issue.
My Code:
# the list with prior calculated values
List=list(0.96,0.89,0.78)
# rendering the condition
condition=character()
for (m in 1:length(List)) {
if (m==length(List)) {
condition=paste0(condition,"List[[",m,"]]>=0.6")
} else {
condition=paste0(condition,"List[[",m,"]]>=0.6 && ")
} # end if-loop
} # end for-loop
# to see what the condition looks like
print(condition)
# the just rendered condition in the if loop
if(condition) {
print("do this ...")
} else {
print("do that ...")
} # end if-loop

You need to parse the text when you use eval:
eval(parse(text=condition))
This returns TRUE in your example, so you can use it as follows:
if(eval(parse(text=condition))) {
print("do this ...")
} else {
print("do that ...")
} # end if-loop
Output:
[1] "do this ..."
You can find more information about eval here: Evaluate expression given as a string

Related

R loop checking condition X times and break if not met

I'd like to create kind of dependency between R and database and for that I'm trying to create a loop which is checking if a date in one column from a database is equal to today's date, if yes then run main statement, if not wait 5mins and try again (max 24 times) then break. I'm stucked with the latter, if someone could advice that would be helpful, thanks!
if(lubridate::date(table$db_date) == Sys.Date()){
print(1)
} else {
Sys.sleep(300)
# and repeat the loop 24 times until statement is TRUE, if not then break
}
If you have an upper limit for the number of iterations, you should use a for loop:
for (i in seq_len(24)) {
if(lubridate::date(table$db_date) == Sys.Date()){
print(1)
break
} else {
Sys.sleep(300)
}
}
Very primitive but maybe something like this:
i=1 # establish global variable
while (T) {
if(lubridate::date(table$db_date) == Sys.Date()){
print(1)
# break
}
if(i < 24 & lubridate::date(table$db_date) != Sys.Date()) { # check both statements
i <<- i+1 # update global variable
Sys.sleep(0.1) # and repeat the loop 24 times until statement is TRUE, if not then break
}
else{break}
}

why c() does not working in this recursive function in R?

enter image description here
I know there exists function 'unique' which works similar to what I want to make, but I want to make this function.
I want this function finally returns 'result' which contains unique elements of input vector.
But I don't know why this function's result is totally different from my expect.
Why c which is to combine before result and new unique element is not working.
Please tell me how to fix my code.
Thank you.
I think what you expect might be something like below, where result should be an argument of m_uni:
m_uni <- function(x,result = c()) {
if (class(x)=='numeric'| class(x)=='character') {
if (length(x) <= 1){
return(result)
} else {
if (x[length(x)] %in% result) {
x <- x[-length(x)]
m_uni(x,result)
} else {
result <- c(result,x[length(x)])
x <- x[-length(x)]
m_uni(x,result)
}
}
} else {
return('This function only gets numeric or character vector')
}
}
such that
> m_uni(x)
[1] 0 4 5 -2

What to set return value for function that normally returns matrix but could fail a conditional

I have a function that is supposed to return a matrix for further functions to use. I have it reading in a file and doing calculations, but I need the main function to skip to the next file if the current one does not meet the correct formatting. This is how basically how I have it now:
for (file in list.files(directory)) {
for (i in 1:length(var)) {
matrix <- foo('someFile.txt',var[i]) # returns matrix under normal conditions
if (typeof(matrix)) == "logical") { # check if foo returns FALSE
warning(paste0('File ',file, ' is not formatted correctly'))
break # skip to next file if so
}
...
}
}
foo <- function(input,seq)
data <- readLines(input)
if (!data[1] %in% c("first","line","values")) {
return(FALSE)
}
...
return(data)
}
But testing the class matrix returns seems clunky and poor technique. Sorry I don't know how to phrase the question better.

if statement in R can only have one line?

I was trying a tiny code with if statement, although it is very simple,but there is something I really confused here is the code
n<-857
while(n!=1){
if(n<=0)
print("please input a positive integer")
else if(n%%2==0)
n<-n/2
print(n)
else
n<-3*n+1
print(n)
}
as we see above,when running this code in R, there comes the error,but if I change the if statement like this
if(n<=0)
print("please input a positive integer")
else if(n%%2==0)
n<-n/2
else
n<-3*n+1
it is ok ,my question is that can we only write one line under each judgement? if I want to do something more after each judge, what should I do ,just like this case, I want to change the value of n,but also want to display it, what should I do? thank you very much
To be precise, this is not about lines but about statements. You can have the whole if else statement in one line:
> if (TRUE) 1 else 3
[1] 1
A statement will end at the end of the line (if complete), you can see that nicely in interactive mode if you enter the code line by line:
> if (TRUE)
+ 1
[1] 1
> else
Fehler: Unerwartete(s) 'else' in "else" # error: unexpected 'else' in "else"
> 3
[1] 3
if can come in form if (condition) statement or if (condition) statement else other.statement, the interpreter assumes the first version is meant if the statement is complete after line 2 - in interactive mode it cannot sensibly wait whether an else appears next. This is different in sourced code - there it is clear with the next line which form it is.
Semicolons end statements as well:
> if (TRUE) 1; else 3
[1] 1
Fehler: Unerwartete(s) 'else' in " else" # error: unexpected 'else' in "else"
But you can only have one statement in each branch of the condition.
> if (TRUE) 1; 2 else 3
[1] 1
Fehler: Unerwartete(s) 'else' in " 2 else" # error: unexpected 'else' in "2 else"
Curly braces group statements so they appear as one statement.
> if (TRUE) {1; 2} else 3
[1] 2
You have to use {} for allows the if statement to have more than one line. Try this:
n<-857
while(n!=1){
if(n<=0){
print("please input a positive integer")
}
else if(n%%2==0){
n<-n/2
print(n)
}
else {
n<-3*n+1
print(n)
}
}
To group statements, surround them with curly braces as you've done with the while loop:
if(n<=0) {
print("please input a positive integer")
} else if(n%%2==0) {
n<-n/2
print(n)
} else {
n<-3*n+1
print(n)
}
This will allow you to place multiple statements inside the if, the else if and the final else.
while the direct answer is, as has been noted, to use curly braces;
it is worth adding that you can integrate the <- assignment operator into many functions.
In your specific case:
print(n <- 3*n+1)
## instead of
# n <- 3*n+1
# print(n)
note that using = here will NOT work. It must be <-
Yes, you can use curly braces to contain more than statements for each conditional statement:
if (condition){
statement 1
print()
}
else{
statement 2
print()
}
Addition: if you want to use only if and else statement in one line you can use this:
ifelse(condition, statement1, statement2)
Ever heard of curly barces?
n<-857
while(n!=1){
if(n<=0) {
print("please input a positive integer")
} else if(n%%2==0) {
n<-n/2
print(n)
} else {
n<-3*n+1
print(n)
}
}

Logical combinations the Java-way: Don't test second case if first is already false

I know that in Java it is often quite handy to do things like that
if(a!=0 && b/a>1){
...;
}
Java stops when the first part is already false. R does not do that, producing errors sometimes. So: Is there a possibility to make this code shorter:
if(exists("user_set_variable")){
if(user_set_variable < 3){
...
}
}
R also short-circuits the && and || operators when the second argument doesn't need to be evaluated. For example (here x does not exist)
> if (exists('x') && x < 3) { print('do this') } else { print ('do that') }
[1] "do that"
From ?'&&' you can find
& and && indicate logical AND and | and || indicate logical OR.
The shorter form performs elementwise comparisons in much the same
way as arithmetic operators. The longer form evaluates left to right
examining only the first element of each vector. Evaluation proceeds
only until the result is determined. The longer form is appropriate
for programming control-flow and typically preferred in if clauses.
So probably you're looking for & instead of &&. See these examples where two conditions are evaluated:
# Case 1
a<- 2
b <- 4
if(a!=0 & b/a>1){
print('Hello World')
} else{
print("one or both conditions not met")
}
[1] "Hello World"
# Case 2
a<- 2
b <- 1
if(a!=0 & b/a>1){
print('Hello World')
} else{
print("one or both conditions not met")
}
[1] "one or both conditions not met"
# Case 3
a<- 0
b <- 1
if(a!=0 & b/a>1){
print('Hello World')
} else{
print("one or both conditions not met")
}
[1] "one or both conditions not met"
Either use the short-circuit statements if those are clear enough as they are or you could just wrap your multiple if statement lines into a function. Here's some pseudo-code for a visual.
if(exists("user_set_variable")){ if(user_set_variable < 3){
... } }
Could then be:
var<- "user_set_variable" 'let var be your variable for this
if(exists(var) && var < 3)
{ 'do stuff }
or do this:
'function definition
Function boolean IsValidVar(variable)
{
if(exists(var))
{
if(var < 3)
{ return true; }}
return false;
}
then your program looks like so:
var<- "user_set_variable" 'let var be your variable for this
if(IsValidVar(var))
{ 'do stuff }
It's really just your call what seems simple.

Resources