################################################################################ ### R BASICS WORKSHOP ### ### PRESENTATION 5: OPERATORS ### ### ### ### Center for Conservation and Sustainable Development ### ### Missouri Botanical Garden ### ### Website: rbasicsworkshop.weebly.com ### ################################################################################ # The material below is largely based on section 3.4 of "R for beginners". It is divided into the following sections: # A. Preliminaries: accessing operator help pages and creation of objects for examples # B. Arithmetic operators # C. Comparison operators (and comments on functions "identical", "all.equal", "is.na", "!is.na", "which") # D. Logical operators # E. Other operators # F. Precedence of operators # G. Optional: examples of operators acting on vectors and matrices of complex numbers # This presentation will cover sections A, B, part of C, D and F. After the presentation, participants # will study on their own the cases 1-6 under section C, as well as section E. Optionally, participants may study # section G. ################################################################################################################################# # A) Preliminaries: accessing operator help pages and creation of objects for examples ################################################################################################################################# # accessing help pages for operators ?+ # this does not work help("+") # this works ?"+" # this works ?* # this does not work help("*") # this works ?"*" # this works # we will use the following vectors in the examples below: #vectors of numbers p <- seq(from = 1, to = 10, by = 1) z <- seq(9, 18, 1) #vectors of character values species.list.1 <- c("Inga adenophylla", "Inga.alba", "Inga amboroensis", "Inga.approximata") species.list.2 <- c("Inga adenophylla", "Inga.alleni", "Inga.amazonica", "Inga.approximata") p z species.list.1 species.list.2 mode(p) class(p) mode(z) class(z) mode(species.list.1) class(species.list.1) mode(species.list.2) class(species.list.2) # we will use the following matrices in the examples below: #matrices of logical values D <- matrix(c(TRUE, FALSE, TRUE, TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE, FALSE), ncol=3) K <- matrix(c(FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, FALSE, FALSE, FALSE, TRUE), ncol=3) #matrices of integer values P <- matrix(seq(1, 25, 1), ncol = 5) Z <- matrix(seq(26, 50, 1), ncol = 5) D K P Z mode(D) class(D) mode(K) class(K) mode(P) class(P) mode(P) class(P) mode(Z) class(Z) ################################################################################################################################# # B) Arithmetic operators ################################################################################################################################# # Arithmetic operators # + Sum # - Subtraction # * Multiplication # / Division # ^ Power # %% Module - calculates the remainder in a division # %/% Integer division - calculates the integer portion of a division # Arithmetic operators act on two objects of mode numeric or complex, # but also on objects of mode logical by coercing logical values to numeric values: 3 + 2 TRUE + FALSE #coercion into numeric TRUE + TRUE #coercion into numeric FALSE + FALSE #coercion into numeric as.numeric(TRUE) #coercion into numeric type as.numeric(FALSE) #coercion into numeric type "Inga.amazonica" + "Inga.alba" #this line of code does not work # The behavior of arithmetic operators depends on the objects on which they act. # Here are six common cases in which arithmetic operators behave differently: ############################################################ # Case 1. Two scalars. 10 + 3 10 - 3 10 * 3 10 / 3 10 ^ 3 10 %% 3 10 %/% 3 ############################################################ # Case 2. A vector or matrix and a scalar. # The operators act on each element of the two objects (the vector and the scalar # or matrix and the scalar). The result is the same size as the vector or matrix. p p - 3 p ^ 3 p %% 3 P P - 3 P ^ 3 P %% 3 ############################################################ # Case 3. Two vectors or matrices of the same size. # The operators act on each element of the two objects (two vectors # or two matrices). The result is the same size as the two vectors or matrices. p z p * z P Z P / Z ############################################################ # Case 4. Two vectors of different size, or a matrix and a vector. # The operation is done "recycling" the elements of the smaller object. # When the length of the larger object is not multiple of the smaller object, # a warning message appears. length(p) p - c(1,2) p - rep(c(1,2), times = 5) p - c(1,2,3) dim(P) P - c(23, 12, 4, 5, 2) P - p ############################################################ # Case 5. Two matrices of different size: it does not work. P - matrix(c(3,2,6,8), ncol=2) P - matrix(p, ncol=2) ############################################################ # Case 6. Operations with NA return NA. p - NA p - c(1, NA) ################################################################################################################################# # C) Comparison operators ################################################################################################################################# # > Greater than # < Less than # >= Greater than or equal to # <= Less than or equal to # == Equal to (note this is not the same as a single "=") # != Not equal to # Comparison operators act on objects of any mode (not just numeric, complex and logical) # and return one or more logical values: 3 > 2 3 >= 2 3 < 2 3 == 2 TRUE > FALSE TRUE > TRUE FALSE == FALSE "Inga.amazonica" == "Inga.alba" "Inga.amazonica" != "Inga.alba" "Inga.amazonica" > "Inga.alba" #lexicographic order, but be careful: see help for operator ">" "Inga.amazonica" < "Inga.alba" # The behavior of comparison operators depends on the objects on which they act. # Here are the six common cases, analogous to those examined above for arithmetic operators: ############################################################ # Case 1. Two elements of length one. 10 < 3 1 == TRUE 1 == FALSE 1 < "Inga.alba" #lexicographic order, but be careful: see help for operator ">" 1 > "Inga.alba" #lexicographic order, but be careful: see help for operator ">" ############################################################ # Case 2. A vector or matrix and an element of length one. # The operators act on each element of the two objects (the vector and the scalar # or matrix and the scalar). The result is the same size as the vector or matrix. p p < 3 p == 3 p != 3 P P < 3 P == 3 P != 3 species.list.1 == "Inga.alba" species.list.1 != "Inga.alba" ############################################################ # Case 3. Two vectors or matrices of the same size. # The operators act on each element of the two objects (two vectors # or two matrices). The result is the same size as the two vectors or matrices. p z p > z P Z P > Z D K D == K species.list.1 == species.list.2 #In the context Cases 3-6 for comparison operators, it is worth mentioning #two functions that compare two objects "wholly": #identical compares the internal representation of the data and returns #TRUE if the objects are strictly identical, and FALSE otherwise (see help page): species.list.1 == species.list.2 identical(species.list.1, species.list.2) identical(species.list.1, species.list.1) species.list.1.B <- as.factor(species.list.1) identical(species.list.1, species.list.1.B) #all.equal compares the "near equality" of two objects, #and returns TRUE or display a summary of the differences (see help page): all.equal(species.list.1, species.list.2) all.equal(species.list.1, species.list.1.B) #be careful when comparing non-integers using operator "==", #as well as functions "identical" and "all.equal"; here are examples #hinting at what might go wrong (see also pages 9-11 of "The R Inferno", and #EXERCISE 3.2: The First Circle of the R Inferno: falling into the Floating Point Trap): 1 - 0.1 #this seems equal to 0.9 0.9 == (1 - 0.1) identical(0.9, 1 - 0.1) all.equal(0.9, 1 - 0.1) 0.9 == (1.1 - 0.2) 1.1 - 0.2 #this seems equal to 0.9 0.9 == (1.1 - 0.2) identical(0.9, 1.1 - 0.2) all.equal(0.9, 1.1 - 0.2) all.equal(0.9, 1.1 - 0.2, tolerance = 1e-15) all.equal(0.9, 1.1 - 0.2, tolerance = 1e-16) 1.2 - 0.3 #this seems equal to 0.9 0.9 == (1.2 - 0.3) identical(0.9, 1.2 - 0.3) all.equal(0.9, 1.2 - 0.3) all.equal(0.9, 1.223 - 0.323, tolerance = 1e-15) all.equal(0.9, 1.2 - 0.3, tolerance = 1e-16) ############################################################ # Case 4. Two vectors of different size, or a matrix and a vector. # The operation is done "recycling" the elements of the smaller object. # When the length of the smaller object is not multiple of the larger object, # a warning message appears. p length(p) p <= c(1,2) p <= rep(c(1,2), time = 5) p > c(1,2,3) P dim(P) P < c(23, 12, 4, 5, 2) P <= p ############################################################ # Case 5. Two matrices of different size: it does not work. P < matrix(c(3,2,6,8), ncol=2) P >= matrix(p, ncol=2) ############################################################ # Case 6. Operations with NA return NA. p < NA p >= c(1, NA) # In the context of comparison operators, Case 6 is related to a situation commonly encountered # in data analysis. Supposse you want to detect NA values in an object (e.g., a vector or a # matrix). One might be tempted to do the following: x <- c(3, NA, 34, 23, 19, NA) x x == "NA" x == NA # clearly, the code above does not work as intended. To detect NA values in an object, the functions # "is.na" and "!is.na" are useful: x is.na(x) !is.na(x) # function "which" might be used along with "is.na" and "!is.na", to determine the position of elements # that have NA values: x which(is.na(x)) which(!is.na(x)) ################################################################################################################################# # D) Logical operators ################################################################################################################################# # & Logical 'and' # && Double form of logical 'and' # | Logical 'or' # || Double form of logical 'or' # xor(x,y) Exclusive 'or' # Logical operators act only on objects of mode logical # and return one or more logical values: TRUE & TRUE TRUE & FALSE FALSE & TRUE 12 & 20 0 & 2 as.logical(12) # coercion to logical type as.logical(0) # coercion to logical type "Inga.alba" & "Inga.amazonica" #this line of code does not work ############################################################ # Operator & # Case 1. Two elements of length one. # is 5 less than three AND 2 greater than 4? 5<3 & 2>4 # This is FALSE because none of comparisons are TRUE # is 5 more than 3 AND 2 greater than 4? 5>3 & 2>4 # This is also FALSE because not all comparisons are TRUE # is 5 more than 3 AND 2 less than 4? 5> 3 & 2<4 # Now both comparisons are TRUE, so all together is also TRUE # Case 2. A vector or matrix and an element of length one. p p>5 & 1<18 # Case 3. two vectors or matrices of the same dimension. p z p>5 & z<18 #this is analogous to case 3 for arithmetic operators 50 & z<18 #analogous to case 3 for arithmetic operators 05 && z<18 p>0 && z<18 # because && deals with single elements, it can do shortcuts (see section 8.2.17 in The R Inferno) 1>2 & "a" 1>2 && "a" ############################################################ # Operator | # Case 1. # is 5 less than 3 OR 2 greater than 4? 5<3 | 2>4 # This is FALSE because NONE of comparisons are TRUE # is 5 greater than 3 OR 2 greater than 4? 5>3 | 2>4 # This is TRUE because at least one comparisons is TRUE # is 5 greater than 3 OR 2 less than 4? 5>3 | 2<4 # This is also TRUE because at least one comparisons is TRUE # Case 2. # Case 3. p z p<5 | z<18 #analogous to case 3 for arithmetic operators # Case 4. # Case 5. # Case 6. Not quite the same as arithmetic operators: NA | NA TRUE | NA FALSE | NA ############################################################ # Operator || p z p<5 || z<18 # because || deals with single elements, it can do shortcuts (see section 8.2.17 in The R Inferno) 1<2 | "a" 1<2 || "a" ############################################################ # Operator xor(x,y) p z xor(p<5, z<18) ################################################################################################################################# # E) Other operators ################################################################################################################################# # here are other operators you may be familiar with, # but feel free to visit the respective help pages: #: sequence operator #-> rightwards assignment #<- assignment (right to left) #= assignment (right to left) #? help # these are operators you may not be familiar with, # and it would be good if you have a chance to visit the respective help pages now, # because we will be using them heavily in the next section of the workshop (6. OBJECT MANIPULATION): #[ [[ indexing #$ @ component / slot extraction # these are other operators you may want to check out by going to the respective help pages: #~ as in formulae #:: ::: access variables in a namespace ################################################################################################################################# # F) Precedence of operators ################################################################################################################################# 1:10-1 1:(10-1) #see ?Syntax ################################################################################################################################# # G) Optional: examples of operators acting on vectors and matrices of complex numbers ################################################################################################################################# #create and examine two vectors of complex numbers m <- complex(real = c(7, -4, -2), imaginary = c(2, -13, 1)) n <- complex(real = c(5, 12, -1, -3, 34, 30, 3, 90, 83, 3), imaginary = c(1, 4, 3, -4, -1, 89, 12, 19, 3, 41)) m n mode(m) class(m) mode(n) class(n) #examples of operators acting on vectors of complex numbers m + 3 m - 10 m * 2 m / 4 m + n m - n m * n m / n m > 1 #complex numbers cannot be ordered like real numbers m > n #complex numbers cannot be ordered like real numbers m == 1 n != 1 is.na(m) is.na(n) !is.na(m) !is.na(n) #create and examine two matrices of complex numbers M <- matrix(complex(real = c(7, -4, -2, 3), imaginary = c(2, -13, 1, -2)), ncol=2) N <- matrix(n, ncol=5) M N mode(M) class(M) mode(N) class(N) #examples of operators acting on matrices of complex numbers M + 3 M - 10 N * 2 N / 4 is.na(M) is.na(N) !is.na(M) !is.na(N)