---
title: "R Functions and Conditional Logic"
output:
  revealjs::revealjs_presentation:
    theme: white
    center: true
    transition: none
    incremental: true
---


```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
knitr::opts_chunk$set(cache=TRUE)
library(knitr)
```


# Conditional Expressions in R

## Exercise: Conditions in R 
We have touched on many of these before, but here are some examples of expressions (conditions) in R. Evaluate these expressions:

```{r, eval=FALSE}
pi > 3 & pi < 3.5
c(1,3,5,7) %in% 1:3
1:3 %in% c(1,3,5,7)
rand.uniform <- runif(n = 1, min = 0, max = 1)
rand.uniform < .5
```

## Solutions: Conditions in R: Evaluated 1

```{r}
pi > 3 & pi < 3.5
c(1,3,5,7) %in% 1:3
1:3 %in% c(1,3,5,7)
```

## Solutions: Conditions in R: Evaluated 2

```{r}
set.seed(01252020)
rand.uniform <- runif(n = 1, min = 0, max = 1); rand.uniform
rand.uniform < .5
```


## Conditional Expression: If and Else
```{r}
print(rand.uniform)
```
Now what does this return?
```{r, eval=FALSE}
if (rand.uniform < .5){
  print('value less than 1/2')
} else {
    print('value greater than or equal to 1/2')
}
```

## Conditional Expression: If and Else
```{r}
print(rand.uniform)
if (rand.uniform < .5){
  print('value less than 1/2')
} else {
    print('value greater than or equal to 1/2')
}
```

## Conditional Expression: Vectorized?
Does this function accept a vector as an input?
```{r, eval=F}
rand.uniform2 <- runif(2)
print(rand.uniform2)
if (rand.uniform2 < .5){
  print('value less than 1/2')
} else {
    print('value greater than or equal to 1/2')
}
```

## Conditional Expression: Vectorized?
```{r, eval=T}
rand.uniform2 <- runif(2)
print(rand.uniform2)
```

## Conditional Expression: Vectorized?
```{r, eval=T}
if (rand.uniform2 < .5){
  'value less than 1/2'
} else {
    'value greater than 1/2'
}
```


## Conditional Expression, ifelse
```{r}
print(rand.uniform2)
ifelse(rand.uniform2 < .5,'less than 1/2',
       'greater than 1/2')
```
The `ifelse()` function is vectorized and generally preferred with a single set of if/else statements.

## Exercise: Conditional Expression
Write a conditional statement that takes a playing card with two arguments:

- (`card.number <- '4'` and `card.suit <- 'C'` = 4 of clubs or `card.number <-'K'` and `card.suit <- 'H'` = King of hearts)  and
- Print `Yes` if the card is a red face card and `No` otherwise.

Verify this works using the following inputs:

- `card.number <- 'J'` and `card.suit <- 'D'`
- `card.number <- 'Q'` and `card.suit <- 'S'`


## Solution: Conditional Expression
\footnotesize
```{r}
card.number <- 'J'
card.suit <- 'D'
ifelse(card.number %in% c('J','Q','K') & 
         card.suit %in% c('H','D'),'Yes','No')
card.number <- 'Q'
card.suit <- 'S'
ifelse(card.number %in% c('J','Q','K') & 
         card.suit %in% c('H','D'),'Yes','No')
```


# Writing R Functions

## Organization: Functions
Functions should contain a comments section immediately below the function definition line. These comments should consist of 

>1. a one-sentence description; 
2. a list of the functions arguments, denoted by `Args:`, with a description of each and 
 3. a description of the return value, denoted by `Returns:`. 
 
 The comments should be descriptive enough that the function can be used without reading the function code.
 
## Overview Functions in R
Functions are a way to save elements of code to be used repeatedly.

```{r}
RollDice <- function(num.rolls){
  # 
  # ARGS: 
  # RETURNS: 
  return(sample(6, num.rolls, replace = T))
}
RollDice(2)
```

## Exercise: Function Descriptions 
Document this function with 

1. a description,
2. summary of input(s)
3. summary of outputs

```{r}
RollDice <- function(num.rolls){
  # 
  # ARGS:
  # RETURNS: 
  return(sample(6, num.rolls, replace = T))
}
```

## Solution: Function Descriptions 

```{r}
RollDice <- function(num.rolls){
  # function that returns rolls of dice
  # ARGS: num.rolls - number of rolls
  # RETURNS: vector of num.rolls of a die
  return(sample(6, num.rolls, replace = T))
}
RollDice(2)
```


## Format of an R function
Here is an example (trivial) R function.
```{r func.def}
SquareRoot <- function(value.in){
  # function takes square root of value.
  # Args: value.in - numeric value 
  # Returns: the square root of value.in
  return(value.in ^ .5)
}
```

## Square Root Function
Now consider running the function for a few values.
```{r evalSQ}
SquareRoot(9)
SquareRoot(25)
```
Now what happens with `SquareRoot(-1)`?

## Square Root Function
```{r neqSQ}
SquareRoot(-1)
```
What should happen?

## Errors in R functions
Here is an example (trivial) R function.
```{r func.def.new}
SquareRoot <- function(value.in){
  # function takes square root of value.
  # Args: value.in - numeric value 
  # Returns: the square root of value.in
  if (value.in < 0) stop('argument less than zero')
  return(value.in ^ .5)
}
```

## Square Root Function
```{r neqSQ.new,eval=FALSE}
SquareRoot(-1)
```
This returns:
```{r error, eval=FALSE}
> SquareRoot(-1)
Error in SquareRoot(-1) : 
  argument less than zero
```

## Exercise: Writing and Documenting a Function
Use the defined style guidelines to create an R script that:

1. Takes a state abbreviations as an input
2. Imports a file available at:  [http://math.montana.edu/ahoegh/teaching/stat408/datasets/HousingSales.csv](http://math.montana.edu/ahoegh/teaching/stat408/datasets/HousingSales.csv)
3. Creates a subset of housing sales from that state.
4. Returns a vector with the mean closing price in that state.

Verify your functions works by running it twice using "MT" and "NE" as inputs.

## Solution: Writing and Documenting a Function
```{r, mysize=TRUE, size='\\tiny'}
SummarizeHousingCosts <- function(state){
  # computes average sales price in a state
  # ARGS: state abbr, such as 'MT' or 'CA'
  # RETURNS: vector with average sales price that each state
  housing.data <- read.csv(
    'http://math.montana.edu/ahoegh/teaching/stat408/datasets/HousingSales.csv')
  location <- subset(housing.data, State == state)
  mean.price <- mean(location$Closing_Price)
  return(mean.price)
}
```


```{r, mysize=TRUE, size='\\footnotesize'}
SummarizeHousingCosts('MT')
SummarizeHousingCosts('NE')
```

## Exercise: Functions Part 2
Now write a function that;

1. Takes daily snowfall total in inches as input
2. Takes day of week as input
3. Returns whether to ski or stay home.

Also include and the `stop()` function for errors.
Test this function with two settings:

 - snowfall = 15, day = "Sat"
 - snowfall = -1, day = "Mon"

## Solution: Functions Part 2
```{r}
ToSki <- function(snowfall, day){
  # determines whether to ski or stay home
  # ARGS: snowfall in inches, day as three letter 
  #       abbrwith first letter capitalized
  # RETURNS: string stating whether to ski or not
  if (snowfall < 0) stop('snowfall should be greater 
        than or equal to zero inches')
  if (day == 'Sat') {
    return('Go Ski')
  } else if (snowfall > 5) {
    return('Go Ski')
  } else return('Stay Home')
}
```

## Solution: Functions Part 2 cont..
```{r, error = T, mysize=TRUE, size='\\small'}
ToSki(snowfall = 15, day = "Sat")
ToSki(-1, 'Mon')
```

