---
title: "functions"
subtitle: "Chapter 15"
theme: flatly 
date: today
toc: true
format:
  html: 
    code-overflow: wrap
    toc: true
    toc-title: "Contents"
    # hide code?

execute:
  warning: false
  message: false
---
   
### General format for writing a function
#     
# ```{r, eval = FALSE}
# name <- function(arguments) {
#   body
# }
# ```
# 
# We'll discuss **3 types of functions:**
# 
# 1. Vector
# 
# 2. Data
# 
# 3. Plotting
# 
# ### Vector Functions
# 
# Motivation for functions
# n <- function(a) {
# 
# 1. Create 4 vectors, each containing 5 random numbers with mean = 2, and standard deviation = 3.
# 2. *Normalize* each vector to have min = 0 and max = 1.
# 3. Notice any inefficency?
# 4. Write a function to normalize a vector and use it.
# 5. Use the function inside `mutate` like this:
# 
# n <- function(a) {
# rng <- range(a, na.rm = TRUE)
# (a - rng[1])/(rng[2] - rng[1])
# }
# 
# ```{r, eval = FALSE}
# # using a function within mutate
# df |> mutate(
#   a = rescale01(a),
#   b = rescale01(b),
#   c = rescale01(c),
#   d = rescale01(d),
# )
# ```
# 
# We can use `across()` to make the above even more efficient
# 
# ### How to compute the mean of many columns
# 
# ```{r}
# library(tidyverse)
# # get the mean of columns a - d.
# df <- tibble(
#   a = rnorm(10),
#   b = rnorm(10),
#   c = rnorm(10),
#   d = rnorm(10)
# )
# 
# print(df)
# df |> summarize(across(a:d, mean))
# ```
# 
# ### How to compute the median of numeric columns
# 
# ```{r}
# glimpse(diamonds)
# diamonds |> summarize(across(where(is.numeric), median))
# ```
# 
# ## The `range` function
# 
# Use the range of a vector to minimize redundancy
# 
# ```{r}
# rescale01 <- function(x) {
#   rng <- range(x, na.rm = TRUE)
#   (x - rng[1]) / (rng[2] - rng[1])
# }
# ```
# 
# ### The z-score
# ```{r}
# z_score <- function(x) {
#   (x - mean(x, na.rm = TRUE)) / sd(x, na.rm = TRUE)
# }
# ```
# 
# ### Clamp
# 
# What happens if you remove the `.default` line?
# 
# ```{r}
# clamp <- function(x, min, max) {
#   case_when(
#     x < min ~ min,
#     x > max ~ max,
#     .default = x
#   )
# }
# 
# clamp(1:10, min = 3, max = 7)
# ```
# 
# ### A function on strings
# ```{r}
# # notice what is gettings assigned TO
# first_upper <- function(x) {
#   str_sub(x, 1, 1) <- str_to_upper(str_sub(x, 1, 1))
#   x
# }
# 
# first_upper("hello")
# ```
# 
# ### A string stripper
# 
# ```{r}
# # the order matters in the str_remove_all's below
# clean_number <- function(x) {
#   is_pct <- str_detect(x, "%")
#   num <- x |> 
#     str_remove_all("%") |> 
#     str_remove_all(",") |> 
#     str_remove_all(fixed("$")) |> 
#     as.numeric()
#   if_else(is_pct, num / 100, num)
# }
# 
# clean_number("$12,300")
# clean_number("45%")
# ```
# 
# ### Summarize functions
# 
# 
# Here's a somewhat advanced version.  Observe the importance of the `:=`
# 
# ```{r}
# f <- function(x,cat_var, num_var){
#     x |> group_by({{cat_var}}) |> 
#         summarize("{{num_var}}" := mean({{num_var}}))
# }
# ```
# 