Search icon CANCEL
Subscription
0
Cart icon
Cart
Close icon
You have no products in your basket yet
Save more on your purchases!
Savings automatically calculated. No voucher code required
Arrow left icon
All Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Newsletters
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Data Analysis with R

You're reading from  Data Analysis with R

Product type Book
Published in Dec 2015
Publisher
ISBN-13 9781785288142
Pages 388 pages
Edition 1st Edition
Languages
Toc

Table of Contents (20) Chapters close

Data Analysis with R
Credits
About the Author
About the Reviewer
www.PacktPub.com
Preface
1. RefresheR 2. The Shape of Data 3. Describing Relationships 4. Probability 5. Using Data to Reason About the World 6. Testing Hypotheses 7. Bayesian Methods 8. Predicting Continuous Variables 9. Predicting Categorical Variables 10. Sources of Data 11. Dealing with Messy Data 12. Dealing with Large Data 13. Reproducibility and Best Practices Index

Functions


If we need to perform some computation that isn't already a function in R a multiple number of times, we usually do so by defining our own functions. A custom function in R is defined using the following syntax:

  function.name <- function(argument1, argument2, ...){
    # some functionality
  }

For example, if we wanted to write a function that determined if a number supplied as an argument was even, we can do so in the following manner:

  > is.even <- function(a.number){
  +   remainder <- a.number %% 2
  +   if(remainder==0)
  +     return(TRUE)
  +   return(FALSE)
  + }
  >
  > # testing it
  > is.even(10)
  [1] TRUE
  > is.even(9)
  [1] FALSE

As an example of a function that takes more than one argument, let's generalize the preceding function by creating a function that determines whether the first argument is divisible by its second argument.

  > is.divisible.by <- function(large.number, smaller.number){
  +   if(large.number %% smaller.number != 0)
  +     return(FALSE)
  +   return(TRUE)
  + 
  }
  >
  > # testing it
  > is.divisible.by(10, 2)
  [1] TRUE
  > is.divisible.by(10, 3)
  [1] FALSE
  > is.divisible.by(9, 3)
  [1] TRUE

Our function, is.even(), could now be rewritten simply as:

  > is.even <- function(num){
  +   is.divisible.by(num, 2)
  + }

It is very common in R to want to apply a particular function to every element of a vector. Instead of using a loop to iterate over the elements of a vector, as we would do in many other languages, we use a function called sapply() to perform this. sapply() takes a vector and a function as its argument. It then applies the function to every element and returns a vector of results. We can use sapply() in this manner to find out which digits in Jenny's phone number are even:

  > sapply(our.vect, is.even)
  [1] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE

This worked great because sapply takes each element, and uses it as the argument in is.even() which takes only one argument. If you wanted to find the digits that are divisible by three, it would require a little bit more work.

One option is just to define a function is.divisible.by.three() that takes only one argument, and use that in sapply. The more common solution, however, is to define an unnamed function that does just that in the body of the sapply function call:

  > sapply(our.vect, function(num){is.divisible.by(num, 3)})
  [1]  TRUE  TRUE FALSE FALSE  TRUE  TRUE  TRUE

Here, we essentially created a function that checks whether its argument is divisible by three, except we don't assign it to a variable, and use it directly in the sapply body instead. These one-time-use unnamed functions are called anonymous functions or lambda functions. (The name comes from Alonzo Church's invention of the lambda calculus, if you were wondering.)

This is somewhat of an advanced usage of R, but it is very useful as it comes up very often in practice.

If we wanted to extract the digits in Jenny's phone number that are divisible by both, two and three, we can write it as follows:

  > where.even <- sapply(our.vect, is.even)
  > where.div.3 <- sapply(our.vect, function(num){
  +   is.divisible.by(num, 3)})
  > # "&" is like the "&&" and operator but for vectors 
  > our.vect[where.even & where.div.3]
  [1] 6 0

Neat-O!

Note that if we wanted to be sticklers, we would have a clause in the function bodies to preclude a modulus computation, where the first number was smaller than the second. If we had, our function would not have erroneously indicated that 0 was divisible by two and three. I'm not a stickler, though, so the functions will remain as is. Fixing this function is left as an exercise for the (stickler) reader.

You have been reading a chapter from
Data Analysis with R
Published in: Dec 2015 Publisher: ISBN-13: 9781785288142
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $15.99/month. Cancel anytime