if statement in R can only have one line? - r

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

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

Dynamically rendered condition for an if loop in 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

R function length error message

I made a function to to compute the sum of I(Xi
my.ecdf<- function(x,y) {
if(!is.null(dim(y)))
stop("y has more than one dimension")
n<-length(x)
i<-1:n
p<-if(x[i]<y) 1 else {
0
}
(sum(p))/n
}
But when I run it with input (rnorm(11),6), I get this error:
Warning message:
In if (x[i] < y) 1 else { :
the condition has length > 1 and only the first element will be used
Any ideas? I'm new to r so sorry if it's something obvious. (Also I don't want to use the for loop)
There are a number of issues in your code:
1) Whats the point of x[1:length(x)] in the if statement? Right now these are meaningless and can be dropped:
n<-length(x)
i<-1:n
x[i]
2) If statement accepts a logical argument not a vector of logical, you can consider adding all() any() etc like
if(all(x < y)) 1 else {0}
or use ifelse() statement for the assignment
3) Finally from what I can understand you overcomplicate things and the whole thing can be written as one-liner:
sum(x < y)/length(x)
This is a logical vector of the same length as y
is.null(dim(y))
You're using it as a logical test. An object with a length greater than 1 can't be unambiguously interpreted by the if statement. Consider if (TRUE FALSE FALSE TRUE) <do something>. When should you do that thing?
If you want to make sure y doesn't have more than one dimension, do
if(length(dim(y)) > 1){
stop("message")
}

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

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