Key Concepts

A function is a data recipe, and a building block of longer scripts.

You can think of functions as input-output machines that take raw data and transform it into useful statistics.

They accepts arguments (data or parameters), and return the requested calculation or transformation.

For example, the mean() function requires a vector of measurements as the input and return the average measure for the group as the output.

VOCABULARY:



0.1 Computer Programs as Recipes

Computer programs are powerful because they allow us to codify recipes for complex tasks, save them, share them, and build upon them.

In the simplest form, a computer program is like a recipe. We have inputs, steps, and outputs.

Ingredients:

Instructions:

  1. Preheat the oven to 375 degrees F.
  2. In a large bowl, mix butter with the sugars until well-combined.
  3. Stir in vanilla and egg until incorporated.
  4. Addflour, baking soda, and salt.
  5. Stir in chocolate chips.
  6. Bake for 10 minutes.

In R, the recipe would look something like this:

function( butter=0.33, sugar=0.5, eggs=1, flour=2, temp=375 )
{
   dry.goods <- combine( flour, sugar )
   batter <- mix( dry.goods, butter, eggs )
   cookies <- bake( batter, temp, time=10 )
   return( cookies )
}

Note that this function to make cookies relies on other functions for each step, combine(), mix(), and bake(). Each of these functions would have to be defined as well, or more likely someone else in the open source community has already written a package called “baking” that contains simple functions for cooking so that you can use them for more complicated recipes.

You will find that R allows you to conduct powerful analysis primarily because you can build on top of and extend a lot of existing functionality.

Assignment of output values

Figure .: Assignment of output values

0.2 Loan Calculator

Let’s look at a slightly more comlicated example by creating an amortization calculator to determine monthly payments that would be required from a home mortgage loan.

Example monthly payment based upon loan amount (P), interest rate (R), and time period of repayment (T).

Figure .: Example monthly payment based upon loan amount (P), interest rate (R), and time period of repayment (T).

Where:

A mortgage calculator considers the total loan amount (the principal), the interest rate or APR (annual percentage rate), and the period of the loan in order to determine how much needs to be paid each month so that payments are distributed equally across the loan term. If we look up a formula, we will find:

We can simplify this formula a bit by putting everything in monthly periods:

\[ PAYMENTS = \frac{principal \cdot interest \ rate}{1-(1+interest \ rate)^{- \ months}} \]

Where:

When we translate this mathematical formula into R code, the new function will look like this:

 calcMortgage <- function( principal, years, APR )
 {
   
    months <- years * 12   # covert years to months
    int.rate <- APR / 12   # convert annual rate to monthly
    
    # amortization formula
    monthly.payment <- ( principal * int.rate ) / 
                       (1 - (1 + int.rate)^(-months) )
    
    monthly.payment <- round( monthly.payment, 2 )
    
    return( monthly.payment )
 
 }
eyJsYW5ndWFnZSI6InIiLCJwcmVfZXhlcmNpc2VfY29kZSI6IiBjYWxjTW9ydGdhZ2UgPC0gZnVuY3Rpb24oIHByaW5jaXBhbCwgeWVhcnMsIEFQUiApXG4ge1xuICAgIG1vbnRocyA8LSB5ZWFycyAqIDEyXG4gICAgaW50LnJhdGUgPC0gQVBSIC8gMTJcbiAgICBcbiAgICAjIGFtb3J0aXphdGlvbiBmb3JtdWxhXG4gICAgbW9udGhseS5wYXltZW50IDwtICggcHJpbmNpcGFsICogaW50LnJhdGUgKSAvIFxuICAgICAgICAgICAgICAgICAgICAgICAoMSAtICgxICsgaW50LnJhdGUpXigtbW9udGhzKSApXG4gICAgXG4gICAgbW9udGhseS5wYXltZW50IDwtIHJvdW5kKCBtb250aGx5LnBheW1lbnQsIDIgKVxuICAgIFxuICAgIHJldHVybiggbW9udGhseS5wYXltZW50IClcbiBcbiB9Iiwic2FtcGxlIjoiIyBDaGVjayB0aGUgZnVuY3Rpb24ncyBhcmd1bWVudHM6XG5hcmdzKCBjYWxjTW9ydGdhZ2UgKVxuXG4jIENhbGN1bGF0ZSBhIG1vcnRnYWdlIGZvciBhICQxMDAsMDAwIGhvdXNlIGZvciAzMCB5ZWFycyB3aXRoIGEgNC41IHBlcmNlbnQgaW50ZXJlc3QgcmF0ZSAoMC4wNDUgQVBSKVxuY2FsY01vcnRnYWdlKCBwcmluY2lwYWw9MTAwMDAwLCB5ZWFycz0zMCwgQVBSPTAuMDQ1ICkgXG5cbiMgVHJ5OiBjYWxjTW9ydGdhZ2UoIHByaW5jaXBhbD0xMDAwMDAgKVxuY2FsY01vcnRnYWdlKCBwcmluY2lwYWw9MTAwMDAwLCBBUFI9MC4wNDUgKSJ9

What happens if you omit an argument from the function? Why?

1 Default Arguments

We can add default values for arguments. These defaults allow us to utilize the function without specifying values for those arguments.

 calcMortgage <- function( principal, years=30, APR=0.05 )
 {
   
    months <- years * 12   # covert years to months
    int.rate <- APR / 12   # convert annual rate to monthly
    
    # amortization formula
    monthly.payment <- ( principal * int.rate ) / 
                       (1 - (1 + int.rate)^(-months) )
    
    monthly.payment <- round( monthly.payment, 2 )
    
    return( monthly.payment )
 
 }
eyJsYW5ndWFnZSI6InIiLCJwcmVfZXhlcmNpc2VfY29kZSI6IiBjYWxjTW9ydGdhZ2UgPC0gZnVuY3Rpb24oIHByaW5jaXBhbCwgeWVhcnM9MzAsIEFQUj0wLjA1IClcbiB7XG4gICAgbW9udGhzIDwtIHllYXJzICogMTJcbiAgICBpbnQucmF0ZSA8LSBBUFIgLyAxMlxuICAgIFxuICAgICMgYW1vcnRpemF0aW9uIGZvcm11bGFcbiAgICBtb250aGx5LnBheW1lbnQgPC0gKCBwcmluY2lwYWwgKiBpbnQucmF0ZSApIC8gXG4gICAgICAgICAgICAgICAgICAgICAgICgxIC0gKDEgKyBpbnQucmF0ZSleKC1tb250aHMpIClcbiAgICBcbiAgICBtb250aGx5LnBheW1lbnQgPC0gcm91bmQoIG1vbnRobHkucGF5bWVudCwgMiApXG4gICAgXG4gICAgcmV0dXJuKCBtb250aGx5LnBheW1lbnQgKVxuIFxuIH0iLCJzYW1wbGUiOiIjIE5vdGljZSB0aGUgbmV3IGRlZmF1bHQgYXJndW1lbnRzOlxuYXJncyggY2FsY01vcnRnYWdlIClcblxuIyBDYWxjdWxhdGUgYSBtb3J0Z2FnZSBmb3IgYSAkMTAwLDAwMCBob3VzZSBmb3IgMzAgeWVhcnMgd2l0aCBhIDQuNSBwZXJjZW50IEFQUlxuY2FsY01vcnRnYWdlKCBwcmluY2lwYWw9MTAwMDAwLCB5ZWFycz0zMCwgQVBSPTAuMDQ1IClcblxuIyBOb3cgdHJ5OiBjYWxjTW9ydGdhZ2UoIHByaW5jaXBhbD0xMDAwMDAgKVxuY2FsY01vcnRnYWdlKCBwcmluY2lwYWw9MTAwMDAwICkifQ==

Note that calcMortgage( principal=100000 ) now works because the function uses the default values for years and APR.

1.1 Defaults

eyJsYW5ndWFnZSI6InIiLCJwcmVfZXhlcmNpc2VfY29kZSI6IiBjYWxjTW9ydGdhZ2UgPC0gZnVuY3Rpb24oIHByaW5jaXBhbCwgeWVhcnM9MzAsIEFQUj0wLjA0NSApXG4ge1xuICAgIG1vbnRocyA8LSB5ZWFycyAqIDEyXG4gICAgaW50LnJhdGUgPC0gQVBSIC8gMTJcbiAgICBcbiAgICAjIGFtb3J0aXphdGlvbiBmb3JtdWxhXG4gICAgbW9udGhseS5wYXltZW50IDwtICggcHJpbmNpcGFsICogaW50LnJhdGUgKSAvIFxuICAgICAgICAgICAgICAgICAgICAgICAoMSAtICgxICsgaW50LnJhdGUpXigtbW9udGhzKSApXG4gICAgXG4gICAgbW9udGhseS5wYXltZW50IDwtIHJvdW5kKCBtb250aGx5LnBheW1lbnQsIDIgKVxuICAgIFxuICAgIHJldHVybiggbW9udGhseS5wYXltZW50IClcbiBcbiB9Iiwic2FtcGxlIjoiYXJncyggY2FsY01vcnRnYWdlIClcblxuIyBDYWxjdWxhdGUgYSBtb3J0Z2FnZSBmb3IgYSAkMTAwLDAwMCBob3VzZSBmb3IgMTUgeWVhcnMgd2l0aCBhIDMgcGVyY2VudCBBUFJcblxuY2FsY01vcnRnYWdlKCBwcmluY2lwYWw9MTAwMDAwLCB5ZWFycz0xNSwgQVBSPTAuMDMgKSJ9

Can you still use custom values for those arguments after defaults are set?

2 Implicit Argument Calls

An explicit call to arguments always uses the formal argument name such as principal=100000.

You can, however, also use implicit argument calls. These rely on the order arguments are specified in the function, and the order of your values in your call.

Implicit arguments calls can be risky, however, because it is very easy to mix them up.

eyJsYW5ndWFnZSI6InIiLCJwcmVfZXhlcmNpc2VfY29kZSI6IiBjYWxjTW9ydGdhZ2UgPC0gZnVuY3Rpb24oIHByaW5jaXBhbCwgeWVhcnM9MzAsIEFQUj0wLjA0NSApXG4ge1xuICAgIG1vbnRocyA8LSB5ZWFycyAqIDEyXG4gICAgaW50LnJhdGUgPC0gQVBSIC8gMTJcbiAgICBcbiAgICAjIGFtb3J0aXphdGlvbiBmb3JtdWxhXG4gICAgbW9udGhseS5wYXltZW50IDwtICggcHJpbmNpcGFsICogaW50LnJhdGUgKSAvIFxuICAgICAgICAgICAgICAgICAgICAgICAoMSAtICgxICsgaW50LnJhdGUpXigtbW9udGhzKSApXG4gICAgXG4gICAgbW9udGhseS5wYXltZW50IDwtIHJvdW5kKCBtb250aGx5LnBheW1lbnQsIDIgKVxuICAgIFxuICAgIHJldHVybiggbW9udGhseS5wYXltZW50IClcbiBcbiB9Iiwic2FtcGxlIjoiIyBUcnkgdGhlc2U6XG5cbmNhbGNNb3J0Z2FnZSggMTAwMDAwLCAzMCwgMC4wNSApXG5cbmNhbGNNb3J0Z2FnZSggMzAsIDEwMDAwMCwgMC4wNSApIn0=

Which of these calculations is correct?

Explain why.

3 Object Assignment vs Argument Assignment

Assignment is the process of assigning a name to an object or value in order to store the data for future use and allow it to be referenced later.

x <- 3

We use assignment in data recipes (scripts) to save values, and in functions to assign values to specific arguments. Note that we use different assignment operators in each case.

Object assignment uses the arrow operator.

Argument assignment inside a function uses the equal sign.

principal <- 100000               # never use equals here
calcMortgage( principal=100000 )  # never use arrows here


Assignment of output values

Figure 3.1: Assignment of output values


4 Your Turn

Create a function to convert Fahrenheit temperatures to Celsius.

  • What arguments do you need?
  • How many decimals do you need? Consider using the round( number, decimals ) function to simplify output.
  • Don’t forget a return statement!

\[ celsius = ( \ fahrenheit − 32 \ ) × \frac{5}{9} \]

If you want to check your work, 212 degees Fahrenheit is equivalent to 100 degrees Celsius.


eyJsYW5ndWFnZSI6InIiLCJzYW1wbGUiOiJjb252ZXJ0VG9DZWxzaXVzIDwtIGZ1bmN0aW9uKCkgICMgYXJndW1lbnRzIGhlcmVcbntcbiAgICAjIHlvdXIgY29kZSBoZXJlXG59XG5cbnRlbXAuaW4uZmFocmVuaGVpdCA8LSAyMTJcbmNvbnZlcnRUb0NlbHNpdXMoIHRlbXAuaW4uZmFocmVuaGVpdCApIn0=

Can you use this function to convert from Celsius to Fahrenheit?