R loop checking condition X times and break if not met - r

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

Related

Does the line break between "}" and "else" really matters?

It is clearly that the documentation of R clearly goes against having a break line between "}" and "else". However, it is odd that the first piece of codes works but the second one does not work (syntax error)
First program
x = 1
stupid_function = function(x){
if(x != 1){
print("haha")
}
else if( x == 1){
print("hihi")
}
}
stupid_function(x)
[1] "hihi"
Second program
x = 1
if(x != 1){
print("haha")
}
else if( x == 1){
print("hihi")
}
Error in source("~/.active-rstudio-document", echo = TRUE) :
~/.active-rstudio-document:6:3: unexpected 'else'
5: }
6: else
In the second program it sees a line at a time as it is typed in so at the point that the line with the } is typed in it cannot know that there will be further lines with an else so it assumes the statement is finished.
In the first case it can see all the code before it is run because it can see all the code in the function so it knows that the } has not finished the statement.
This line of argument works for an if/else but does not work in general. For example, this will produce an error when the function is
defined.
f <- function(x) {
x
* 2
}
Note that the if else need not be in a function for it to work. It just need to be in a continuous form or in a way to be expressed as a continuous block of code. One way is being in a function. The other is to write it in one line, or even ensure that there is no line break between the if block and the else block:
x <- 1
if(x != 1) print('haha') else print('hihi')
[1] "hihi"
More blocks of statements:
x <- 1
if(x != 1){
print("haha")
} else if( x == 1){ # Note how else begins immediatley after }
print("hihi")
}
[1] "hihi"
Note that you need to know when to put the line breaks whether in a function or outside of a function. Otherwise the code might fail or even give incorrect results.
Using subtraction:
x <- 1
x -
2
[1] -1
x <- 1
x
- 2
[1] -2
You need to know when/where to have the line breaks. Its always safe to have else follow the closing brace } of the previous if statement. ie:
if(...){
....
} else if(...){
....
} else {
...
}

Multiple conditions in if statements in R

I am trying to cut down a list of gene names that I have been given. I'm trying to eliminate any repetitive names that may be present but I keep getting an error when running my code:
counter=0
i=0
j=0
geneNamesRevised=array(dim=length(geneNames))
for (i in 0:length(geneNamesRevised))
geneNamesRevised[i]=""
geneNamesRevised
for (i in 1:length(geneNames))
for (j in 1:length(geneNamesRevised))
if (geneNames[i]==geneNamesRevised[j])
{
break
}
else if ((j==length(geneNamesRevised)-1) &&
(geneNames[i]!=geneNamesRevised[j]))
{
geneNamesRevised[counter]=geneNames[i]
counter++
}
The error message is a repetitive string of :
the condition has length > 1 and only the first element will be usedthe condition has length > 1 and only the first element will be usedthe condition has length > 1 and only the first element will be used
and this error message is for the last "else if" statement that has the '&&'.
Thank you!
Why not just
geneNamesRevised <- unique( geneNames )
... which returns a shortened list. There is also a duplicated function that can be used to remove duplicates when negated.
There are a few problems in your code.
1) The else is incorrectly specified - or not :) thanks #Mohsen_Fatemi
2) & is usually what you need rather than &&
3) counter++ isn't R
Copy the code below and see if it runs
for (i in 1:length(geneNames)){
for (j in 1:length(geneNamesRevised)){
if (geneNames[i]==geneNamesRevised[j])
{
break
} else {
if ((j==length(geneNamesRevised)-1) & (geneNames[i]!=geneNamesRevised[j]))
{
geneNamesRevised[counter]=geneNames[i]
counter <- counter + 1
}
}
}
}
Edit
4) also you were missing braces for your fors
use & instead of && ,
else if ((j==length(geneNamesRevised)-1) & (geneNames[i]!=geneNamesRevised[j]))

R -- screening Excel rows according to characteristics of multiple cells

I am trying to eliminate all rows in excel that have he following features:
First column is an integer
Second column begins with an integer
Third column is empty
The code I have written appears to run indefinitely. CAS.MULT is the name of my dataframe.
for (i in 1:nrow(CAS.MULT)) {
testInteger <- function(x) {
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if (test == TRUE) {
return (TRUE)
}
else {
return (FALSE)
}
}
if (testInteger(as.integer(CAS.MULT[i,1])) == TRUE) {
if (testInteger(as.integer(substring(CAS.MULT[i,2],1,1))) == TRUE) {
if (CAS.MULT[i,3] == '') {
CAS.MULT <- data.frame(CAS.MULT[-i,])
}
}
}
}
You should be very wary of deleting rows within a for loop, if often leads to undesired behavior. There are a number of ways you could handle this. For instance, you can flag the rows for deletion and then delete them after.
Another thing I noticed is that you are converting your columns to integers before passing them to your function to test if they are integers, so you will be incorrectly returning true for all values passed to the function.
Maybe something like this would work (without a reproducible example it's hard to say if it will work or not):
toDelete <- numeric(0)
for (i in 1:nrow(CAS.MULT)) {
testInteger <- function(x) {
test <- all.equal(x, as.integer(x), check.attributes = FALSE)
if (test == TRUE) {
return (TRUE)
}
else {
return (FALSE)
}
}
if (testInteger(CAS.MULT[i,1]) == TRUE) {
if (testInteger(substring(CAS.MULT[i,2],1,1)) == TRUE) {
if (CAS.MULT[i,3] == '') {
toDelete <- c(toDelete, i)
}
}
}
}
CAS.MULT <- CAS.MULT[-1*toDelete,]
Hard to be sure without testing my code on your data, but this might work. Instead of a loop, the code below uses logical indexing based on the conditions you specified in your question. This is vectorized (meaning it operates on the entire data frame at once, rather than by row) and is much faster than looping row by row:
CAS.MULT.screened = CAS.MULT[!(CAS.MULT[,1] %% 1 == 0 |
as.numeric(substring(CAS.MULT[,2],1,1)) %% 1 == 0 |
CAS.MULT[,3] == ""), ]
For more on checking whether a value is an integer, see this SO question.
One other thing: Just for future reference, for efficiency you should define your function outside the loop, rather than recreating the function every time through the loop.

How to setup a recursive lapply for specific values ex.w[i] == n[i]?

Background
I'm developing a function that takes in a value for w between 1 and 3 and returns n values from one of 3 distributions.
The problem I am having is when n or w are not of length 1. So I've added 2 parameters nIsList and wIsList to create the functionality I want. The way I want this to work is as follows:
(Works as needed)
If nIsList ex( c(1,2,3) ) return a list equivalent to running consume(w,1), consume(w,2), consume(w,3)
(Works as needed)
If wIsList ex( c(1,2,3) ) return a list equivalent to running consume(1,n), consume(2,n), consume(3,n)
(Doesn't work as needed)
If nIsList ex(1,2,3) and wIsList ex(1,2,3)
return a list equivalent to running consume(1,1), consume(2,2), consume(3,3). Instead, I get a list equivalent to running [consume(1,1), consume(1,2), consume(1,3)], [consume(2,1), consume(2,2), consume(2,3)], [consume(3,1),consume(3,2), consume(3,3)]
I understand why I am getting the results I am getting. I just can't seem to figure out how to get the result I want. (As explained above)
Question
I want the function to provide a list for each element in w and n that is consume(w[i], n[i]) when wIsList & nIsList are True. Is there a way to do that using lapply?
The code:
library("triangle")
consume <- function(w, n=1, nIsList=F, wIsList=F){
if(!nIsList & !wIsList){
if(w==1){
return(rtriangle(n,0.3,0.8))
}else if(w==2){
return(rtriangle(n,0.7,1))
}else if(w==3){
return(rtriangle(n,0.9,2,1.3))
}
}
else if(nIsList & !wIsList){
return(sapply(n, consume, w=w))
}
else if(nIsList & wIsList){
return(lapply(n, consume, w=w, wIsList=T))
}
else if(!nIsList & wIsList){
return(lapply(w, consume, n))
}
}
Note: I am having trouble summarizing this question. If you have any suggestions for renaming it please let me know and I will do so.
Thanks to JPC's comment, using mapply does the trick. The new code is as follows:
consume <- function(w, n=1){
nIsList <- length(n) > 1 # Change based on JPC's second comment
wIsList <- length(w) > 1 # Change based on JPC's second comment
if(!nIsList & !wIsList){
if(w==1){
return(rtriangle(n,0.3,0.8))
}else if(w==2){
return(rtriangle(n,0.7,1))
}else if(w==3){
return(rtriangle(n,0.9,2,1.3))
}
}
else if(nIsList & !wIsList){
return(sapply(n, consume, w=w))
}
else if(nIsList & wIsList){
return(mapply(consume,w,n)) ## Updated portion
}
else if(!nIsList & wIsList){
return(lapply(w, consume, n))
}
}

For loop in R is printing twice

I'm fairly new to programming and am avidly trying to learn R. I am attempting to solve the classic "Fizzbuzz" problem in R and have almost figured out a way, but my loop is printing twice. Tried debugging and searching, but I can't seem to find anything. Any suggestions?
tl;dr Do you know why this for loop prints twice?
fizzbuzz = function(n){
if ( n %% 15 == 0 ) {
print("Fizzbuzz")
} else
if ( n %% 5 == 0 ) {
print("buzz")
} else
if ( n %% 3 == 0 ) {
print("Fizz")
} else {
print(n)
}
}
for (a in 1:100)
print(fizzbuzz(a))
Because you call print twice, once in the function and once in the loop. Remove the print in the loop and it only prints once.
for (a in 1:100)
fizzbuzz(a)
You are printing the result of fizzbuzz and inside the function. Try this:
for (a in 1:100)
fizzbuzz(a)

Resources