Unit2 R Notes
Unit2 R Notes
UNIT 2
Control statements in R
Control statements are expressions used to control the execution and flow of the
program based on the conditions provided in the statements. These structures are
used to make a decision after assessing the variable.
In R programming, there are 8 types of control statements as follows:
if condition
if-else condition
for loop
nested loops
while loop
repeat and break statement
return statement
next statement
if condition
This control structure checks the expression provided in parenthesis is true or not. If
true, the execution of the statements in braces {} continues.
Syntax:
if(expression){
statements
....
....
}
Ex:
x <- 100
Output
"100 is greater than 10"
if-else condition
It is similar to if condition but when the test expression in if condition fails, then
statements in else condition are executed.
Syntax:
if(expression){
statements
....
....
}
else{
statements
....
....
}
Ex:
x <- 5
for loop
It is a type of loop or sequence of statements executed repeatedly until exit
condition is reached.
Syntax:
for(value in vector){
statements
....
....
}
Ex:
x <- letters[4:10]
for(i in x){
print(i)
}
Output:
[1] "d"
[1] "e"
[1] "f"
[1] "g"
[1] "h"
[1] "i"
[1] "j"
Nested loops
Nested loops are similar to simple loops. Nested means loops inside loop. Moreover,
nested loops are used to manipulate the matrix.
Ex:
# Defining matrix
m <- matrix(2:15, 2)
for (r in seq(nrow(m))) {
for (c in seq(ncol(m))) {
print(m[r, c])
}
}
Output:
[1] 2
[1] 4
[1] 6
[1] 8
[1] 10
[1] 12
[1] 14
[1] 3
[1] 5
[1] 7
[1] 9
[1] 11
[1] 13
[1] 15
while loop
while loop is another kind of loop iterated until a condition is satisfied. The testing
expression is checked first before executing the body of loop.
Syntax:
while(expression){
statement
....
....
}
Ex:
x=1
# Print 1 to 5
while(x <= 5){
print(x)
x=x+1
}
Output:
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
# Print 1 to 5
repeat{
print(x)
x=x+1
if(x > 5){
break
}
}
Output:
[1] 1
[1] 2
[1] 3
[1] 4
[1] 5
return statement
return statement is used to return the result of an executed function and returns
control to the calling function.
Syntax:
return(expression)
Ex:
# Checks value is either positive, negative or zero
func <- function(x){
if(x > 0){
return("Positive")
}else if(x < 0){
return("Negative")
}else{
return("Zero")
}
}
func(1)
func(0)
func(-1)
Output:
[1] "Positive"
[1] "Zero"
[1] "Negative"
next statement
next statement is used to skip the current iteration without executing the further
statements and continues the next iteration cycle without terminating the loop.
Ex:
# Defining vector
x <- 1:10
apply(): This function applies a given function over the margins of a given array.
apply(array, margins, function, …)
array = list of elements
margins = dimension of the array along which the function needs to be applied
function = the operation which you want to perform
Example:
# R program to illustrate
# apply() function
# Creating a matrix
A = matrix(1:9, 3, 3)
print(A)
Output:
[, 1] [, 2] [, 3]
[1, ] 1 4 7
[2, ] 2 5 8
[3, ] 3 6 9
[1] 12 15 18
[1] 6 15 24
lapply(): This function is used to apply a function over a list. It always returns a list of
the same length as the input list.
lapply(list, function, …)
list = Created list
function = the operation which you want to perform
Example:
# R program to illustrate
# lapply() function
# Creating a matrix
A = matrix(1:9, 3, 3)
# Creating a list
myList = list(A, B)
# applying lapply()
determinant = lapply(myList, det)
print(determinant)
Output:
[[1]]
[1] 0
[[2]]
[1] 5.329071e-15
# Creating a list
A = list(a = 1:5, b = 6:10)
# applying sapply()
means = sapply(A, mean)
print(means)
Output:
ab
38
A vector is returned since the output had a list with elements of length 1.
tapply(): This function is used to apply a function over subset of vectors given by a
combination of factors.
tapply(vector, factor, function, …)
vector = Created vector
factor = Created factor
function = the operation which you want to perform
Example:
# R program to illustrate
# tapply() function
# Creating a factor
Id = c(1, 1, 1, 1, 2, 2, 2, 3, 3)
# Creating a vector
val = c(1, 2, 3, 4, 5, 6, 7, 8, 9)
# applying tapply()
result = tapply(val, Id, sum)
print(result)
Output:
1 2 3
10 18 17
How does the above code work?
mapply(): It’s a multivariate version of lapply(). This function can be applied over
several list simultaneously.
mapply(function, list1, list2, …)
function = the operation which you want to perform
list1, list2 = Created lists
Example:
# R program to illustrate
# mapply() function
# Creating a list
A = list(c(1, 2, 3, 4))
# Applying mapply()
result = mapply(sum, A, B)
print(result)
Output:
24
If-Else statement in R
== Equal x == y
!= Not equal x != y
The if Statement
An "if statement" is written with the if keyword, and it is used to specify a block of
code to be executed if a condition is TRUE:
Example:
a<-33
b<-200
if(b>a){
print(“b is greater than a”)
}
In this example we use two variables, a and b, which are used as a part of the if
statement to test whether b is greater than a. As a is 33, and b is 200, we know that
200 is greater than 33, and so we print to screen that "b is greater than a".
R uses curly brackets { } to define the scope in the code.
Else If
The else if keyword is R's way of saying "if the previous conditions were not true,
then try this condition":
Example
a <- 33
b <- 33
if (b > a) {
print("b is greater than a")
} else if (a == b) {
print ("a and b are equal")
}
In this example a is equal to b, so the first condition is not true, but the else
if condition is true, so we print to screen that "a and b are equal".
You can use as many else if statements as you want in R.
If Else
The else keyword catches anything which isn't caught by the preceding conditions:
Example
a<-200
b<-33
if(b>a){
print(“b is greater than a”)
}else if(a==b){
print(“a and b are equal”)
}else{
print(“a is greater than b”)
}
In this example, a is greater than b, so the first condition is not true, also the else
if condition is not true, so we go to the else condition and print to screen that "a is
greater than b".
You can also use else without else if:
Example
a<-200
b<-33
if(b>a){
print(“b is greater than a”)
} else{
print(“a is greater than a”)
}
OPERATORS
R has many operators to carry out different mathematical and logical
operators.
Types of operators are:
Arithmetic Operators
Relational Operators
Logical Operators
Assignment Operators
Miscellaneous Operators
Arithmetic Operators:
These operators are used to carry out mathematical operations like addition
and multiplication. The list of arithmetic operators available in R are:
Operator Description Example
+ Adds two vectors >v<-c(2,5.5,6)
>t<-c(8,3,4)
>print(v+t)
[1] 10.0 8.5 10.0
- Subtracts second vector from the first >v<-c(2,5.5,6)
>t<-c(8,3,4)
>print(v-t)
[1] -6.0 2.5 2.0
* Multiplies both vectors >v<-c(2,5.5,6)
>t<-c(8,3,4)
>print(v*t)
[1] 16.0 16.5 24.0
/ Divide the first vector with the >v<-c(2,5.5,6)
second >t<-c(8,3,4)
>print(v/t)
[1]0.250000 1.833333
1.500000
Relational Operator:
Relational Operators are used to compare between values. Each element of the first
vector is compared with the corresponding element of the second vector. The result
of comparison is a boolean value.
Operator Description Example
> Checks if each element of >v<-c(2,5.5,6,9)
the first vector is greater >t<-c(8,2.5,1,9)
than the corresponding >print(v>t)
element of the second O/p FALSE TRUE TRUE
vector FALSE
< Checks if each element of >v<-c(2,5.5,6,9)
the first vector is less than >t<-c(8,2.5,1,9)
the corresponding >print(v<t)
element of the second O/p TRUE FALSE FALSE
vector FALSE
== Checks if each element of >v<-c(2,5.5,6,9)
the first vector is equal to >t<-c(8,2.5,1,9)
the corresponding >print(v==t)
element of the second O/p FALSE FALSE FALSE
vector TRUE
<= Checks if each element of >v<-c(2,5.5,6,9)
the first vector is less than >t<-c(8,2.5,1,9)
or equal to the >print(v<=t)
corresponding element of O/p TRUE FALSE FALSE
the second vector TRUE
>= Checks if each element of >v<-c(2,5.5,6,9)
the first vector is greater >t<-c(8,2.5,1,9)
than or equal to the >print(v>=t)
corresponding element of O/p FALSE TRUE TRUE
the second vector TRUE
!= Checks if each element of >v<-c(2,5.5,6,9)
the first vector is not >t<-c(8,2.5,1,9)
equal to the >print(v!=t)
corresponding element of O/p TRUE TRUE TRUE
the second element FALSE
Logical Operator:
It is applicable only to vectors of type logical, numeric or complex. Zero is
considered FALSE and non-zero numbers are taken as TRUE. Each element of the
first vector is compared with the corresponding element of the second vector. The
result of comparison is a boolean value.
Operator Description Example
& It is called element-wise >v<-c(3,2,TRUE,2+3i)
logical AND operator. It >t<-c(4,1,FALSE,2+3i)
combines each element of >print(v&t)
the first vector with the O/p TRUE TRUE FALSE
corresponding element of TRUE
the second vector and
gives a output TRUE if
both the elements are
TRUE
| It is called element-wise >v<-c(3,0,TRUE,2+3i)
logical OR operator. It >t<-c(4,0,FALSE,2+3i)
combines each element of >print(v|t)
the first vector with the O/p TRUE FALSE TRUE
corresponding element of TRUE
the second vector and
gives a output TRUE if one
the elements is TRUE
! It is called logical NOT >v<-c(3,2,FALSE,2+3i)
operator. Takes each >print(!v)
element of the vector and O/p FALSE FALSE TRUE
gives the opposite logical FALSE
value
The logical operator && and || considers only the first element of the vectors and
give a vector of single element as output
Assignment Operators:
These operators are used to assign values to vectors
Operators Description Example
<- Called left assignment >v1<-c(3,1,TRUE,2+2i)
Or >v2=c(3,1,TRUE,2+2i)
= >v3<<-c(3,1,TRUE,2+2i)
<<- >print(v1)
>print(v2)
>print(v3)
O/p 3+0i 1+0i 1+0i 2+2i
3+0i 1+0i 1+0i 2+2i
3+0i 1+0i 1+0i 2+2i
-> Called right assignment >c(3,1,TRUE,2+2i)->v1
Or >c(3,1,TRUE,2+2i)->> v2
->> >print(v1)
>print(v2)
O/p 3+0i 1+0i 1+0i 2+2i
3+0i 1+0i 1+0i 2+2i
Miscellaneous Operators:
These operators are used for specific purpose and not general mathematical
or logical computation.
Default Arguments
Ex 1:
calculate_square<-function(n)
{
result<-n^2
return(result)
}
value1<-2
calculate_square(value1)
value2<-3.2
calculate_square(value2)
O/p
[1]4
[1]10.24
Ex 2:
calculate_square<-function(n)
{
result<-n^2
return(result)
}
calculate_square(2)
calculate_square(3.2)
O/p
[1]4
[1]10.24
divisible(100,5)
divisible(7,3)
divisible(9,2)
O/p
"100 is divisible by 5"
"7 is not divisible by 3"
[1] "9 is not divisible by 2"
O/p:
"12 is divisible by 3"
"10 is divisible by 5"
Dot argument:
Dot argument(…) is also known as ellipsis which allows the function to take
an undefined number of arguments. It allows the function to take an arbitrary
number of arguments.
Ex:
func<-function(n,...)
{
l<-list(n,...)
paste(l,collapse=",")
}
func(5,1L,6i,TRUE,"DOT Operator")
O/p
[1] "5,1,0+6i,TRUE,DOT Operator"
Function as argument:
In R programming, functions can be passed to another functions as
arguments.
Ex:
func<-function(n,fun1)
{
return(fun1(x))
}
func(c(1:10),sum)
func(c(1,2,3,4),mean)
O/p
[1] 36
[1] 4.5
RETURN VALUES
O/p
[1]10
#build it again, this time with another argument after the explicit return
> num<-function(x)
+{
+ return(x*2)
+ print("RAM")
+ return(17)
+}
> num(5)
O/p
[1] 10
#if the last statement is for loop or any empty statement then it return NULL
> num<-function(x)
+{
+
+}
> num(5)
O/p
NULL
O/p
[[1]]
[1] 30
[[2]]
[1] -10
[[3]]
[1] 200
[[4]]
[1] 0.5
Good software design can glance through a function’s code and immediately spot
the various points at which contains is returned to the called. The easiest way to
accomplish this to use an explicit return() call in all lines in the middle of the code
that cause a return.
RETURNING COMPLEX OBJECTS
In R, when we refer to “complex objects”,we generally mean data structures that can
hold multiple types of data or structures such as lists, data-frames and matrices.
These complex objects can be created and returned from functions to encapsulate
and organize related information.
Ex:
Returning a list
> create_complex_list<-function(x,y){
+ returnlist<-list(add=x+y,sub=x-y,prod=x*y,div=x/y)
+ return(returnlist)
+}
> create_complex_list(5,3)
$add
[1] 8
$sub
[1] 2
$prod
[1] 15
$div
[1] 1.666667
Returning dataframe
> create_complex_dataframe<-function(x,y){
+ returndf<-[Link](add=x+y,sub=x-y,prod=x*y,div=x/y)
+ return(returndf)
+}
> create_complex_dataframe(5,3)
add sub prod div
1 8 2 15 1.666667
Returning matrices
> create_complex_matrix<-function(x,y){
+ returnmatrix<-matrix(c(x+y,x-y,x*y,x/y),nrow=2)
+ return(returnmatrix)
+}
> create_complex_matrix(5,3)
[,1] [,2]
[1,] 8 15.000000
[2,] 2 1.666667
Function() is a built-in R function whose job is to create functions, on the right hand
side, there are really two arguments to function(): The first is the formal argument
list for the function i.e., x & the second is the body of the function return (x+1).
> g<-function(h,a,b){
+ h(a,b)
+ g(f1,2,3)
+ }
NO POINTERS IN R
R does not have variables corresponding to pointers or references like c language.
This can make programming more difficult in some cases.
The fundamental thought is to create a class constructor and have every
instatiation of class be its own environment. One can then pass the object/ condition
into a function and it will be passed by reference instead of by value, because unlike
other R objects, environments are not copied when passed to functions. Changes to
the objects in the function will change the object in he calling frame. In this way, one
can operate on the object and change internal elements without having to create a
copy of the object when the function is called, nor pass the entire object back from
the function. For large objects, this saves memory and time.
Ex:
> x<-c(12,4,6)
> sort(x)
[1] 4 6 12
> x
[1] 12 4 6
The argument to sort() does not change. If we do want x to change in this R code, the
solution is to reassign the arguments:
> x<-sort(x)
> x
[1] 4 6 12
If a function has several output then a solution is to gather them together into a list,
call the function with this list as an argument, have the function return the list, and
then reassign to the original list.
Ex:
> y<-function(x){
+ odds<-which(x%%2!=0)
+ evens<-which(x%%2==0)
+ list(o=odds,e=evens)
+ }
> x<-c(2,34,1,5)
> y(x)
$o
[1] 3 4
$e
[1] 1 2
RECURSION
Recursion is a programming technique in which, a function calls itself repeatedly for
some input. To solve a problem of type x by writing a recursive function f():
1. Break the original problem of type x into one or more smaller problems of type x
2. Within f(), call f() on each of the smaller problems
3. Within f(), piece together the results of (b) to solve the original problem
Tracing
QUICK SORT IMLEMENTATION
A quick sort is also known as partition-exchange sort and is based on Divide and
Conquer Algorithm design method. This was proposed by C.A.R Hoare. The basic idea
of quick sort is very simple. We consider one element at a time (pivot element). We
have to move the pivot element to the final position that it should occupy in the final
sorted list. While identifying this position, we arrange the elements, such that the
elements to the left of the pivot element will be less than the pivot element and
elements to the right of the pivot element will be greater than the pivot element.
There by dividing the list 2 parts. We have to apply quick sort on these 2 parts
recursively until the entire list is sorted
Ex:
> quicksort<-function(arr){
+ if(length(arr)<=1){
+ return(arr)
+ }
+ pivot<-arr[1]
+ less_than_pivot<-arr[arr<pivot]
+ equal_to_pivot<-arr[arr==pivot]
+ greater_than_pivot<-arr[arr>pivot]
+ sorted_less<-quicksort(less_than_pivot)
+ sorted_greater<-quicksort(greater_than_pivot)
+ sorted_array<-c(sorted_less,equal_to_pivot,sorted_greater)
+ return(sorted_array)
+ }
> unsorted_array<-c(4,5,3,2,6)
> sorted_array<-quicksort(unsorted_array)
> cat("Unsorted array",unsorted_array)
Unsorted array 4 5 3 2 6
> cat("sorted_array",sorted_array)
sorted_array 2 3 4 5 6
Ex: 8,5,2,6,20
8
/\
5 20
/\
2 6
Program
Node<-function(key){
list(key=key,left=NULL,right=NULL)
}
root<-NULL
keys_to_insert<-c(8,3,10,1,6,14,4,7,1,3)
for(key in keys_to_insert){
root<-insert(root,key)
}
#search for keys in the BST
keys_to_search<-c(6,5)
for(key in keys_to_search){
result<-search(root,key)
if(){
cat("key",key,"found in the BST.\n")
}else{
cat("key",key,"not found in the BST.\n")
}
}
O/p:
key 6 found in the BST.
key 5 not found in the BST.
ERROR HANDLING IN R
Error handling is a process in which we deal with unwanted or anomalous errors
which may cause abnormal termination of the program during its execution.
In R programming there are two ways to implement an error handling mechanism.
Either we can directly call the functions like stop() or warning() or we can use the
error options such as “warn” or “[Link]”.
Condition Handling in R:
There are basically three methods to handle such conditions and errors in R:
try(): it helps us to continue with the execution of the program even when an
error occurs
tryCatch(): It helps to handle the conditions and control whats happens based
on the conditions.
withCallingHandlers(): It is alternative to tryCatch() that takes care of the local
handlers.
Try-catch-finally in R:
Unlike other programming languages such as Java, C++, and so on, the try-
catch-finally statements are used as a function in R. The main two condtions are
handled in tryCatch() are “errors” and “warnings”.
Syntax:
check=tryCatch({
expression
},warning=function(w){
code that handles the warnings
},error=function(e){
code that handles the errors
},finally=function(f){
clean up code
})
Ex:
# Function to simulate an error
divide_numbers <- function(x, y) {
if (y == 0) {
stop("Error: Division by zero")
}
return(x / y)
}
O/p
Caught an error: Error: Division by zero
Finally block executed
[1] NA
withCallingHandlers() in R:
In R, withCallingHandlers() is a variant of tryCatch(). The only difference is
tryCatch() deals with exiting handlers while withCallingHandlers() deal with local
handlers.
Ex:
# Function to simulate an error
divide_numbers <- function(x, y) {
if (y == 0) {
stop("Error: Division by zero")
}
return(x / y)
}
O/p
Caught an error: Error: Division by zero
Show Traceback