Returning values
from functions
INTRODUCTION TO WRITING FUNCTIONS IN R
Richie Co on
Curriculum Architect at DataCamp
A simple sum function
simple_sum <- function(x) {
if(anyNA(x)) {
return(NA)
}
total <- 0
for(value in x) {
total <- total + value
}
total
}
simple_sum(c(0, 1, 3, 6, NA, 7))
NA
INTRODUCTION TO WRITING FUNCTIONS IN R
Geometrics means again
calc_geometric_mean <- function(x, [Link] = FALSE) {
assert_is_numeric(x)
if(any(is_non_positive(x), [Link] = TRUE)) {
stop("x contains non-positive values, so the geometric mean makes no sense.")
}
[Link] <- coerce_to(use_first([Link]), "logical")
x %>%
log() %>%
mean([Link] = [Link]) %>%
exp()
}
INTRODUCTION TO WRITING FUNCTIONS IN R
Returning NaN with a warning
calc_geometric_mean <- function(x, [Link] = FALSE) {
assert_is_numeric(x)
if(any(is_non_positive(x), [Link] = TRUE)) {
warning("x contains non-positive values, so the geometric mean makes no sense.")
return(NaN)
}
[Link] <- coerce_to(use_first([Link]), "logical")
x %>%
log() %>%
mean([Link] = [Link]) %>%
exp()
}
INTRODUCTION TO WRITING FUNCTIONS IN R
Reasons for returning early
1. You already know the answer.
2. The input is an edge case.
INTRODUCTION TO WRITING FUNCTIONS IN R
Hiding the return value
simple_sum <- function(x) {
if(anyNA(x)) {
return(NA)
}
total <- 0
for(value in x) {
total <- total + value
}
total
}
simple_sum(c(0, 1, 3, 6, 2, 7))
19
INTRODUCTION TO WRITING FUNCTIONS IN R
Hiding the return value
simple_sum <- function(x) {
if(anyNA(x)) {
return(NA)
}
total <- 0
for(value in x) {
total <- total + value
}
invisible(total)
}
simple_sum(c(0, 1, 3, 6, 2, 7))
INTRODUCTION TO WRITING FUNCTIONS IN R
Many plots invisibly return things
ggplot(snake_river_visits, aes(n_visits)) +
geom_histogram(binwidth = 10)
INTRODUCTION TO WRITING FUNCTIONS IN R
Many plots invisibly return things
srv_hist <- ggplot(snake_river_visits, aes(n_visits)) +
geom_histogram(binwidth = 10)
str(srv_hist, [Link] = 0)
List of 9
- attr(*, "class")= chr [1:2] "gg" "ggplot"
INTRODUCTION TO WRITING FUNCTIONS IN R
Let's practice!
INTRODUCTION TO WRITING FUNCTIONS IN R
Returning multiple
values from
functions
INTRODUCTION TO WRITING FUNCTIONS IN R
Richie Co on
Curriculum Architect at DataCamp
Getting the session information
[Link] loadedNamespaces()
"R version 3.5.3 (2019-03-11)" [1] "Rcpp" "grDevices" "crayon"
[4] "dplyr" "assertthat" "R6"
[Link]()[c("sysname", "release")] [7] "magrittr" "datasets" "pillar"
[10] "rlang" "utils" "praise"
[13] "rstudioapi" "graphics" "base"
sysname release
[16] "tools" "glue" "purrr"
"Linux" "4.14.106-79.86.amzn1.x86_64"
[19] "yaml" "compiler" "pkgconfig"
[22] "stats" "tidyselect" "methods"
[25] "tibble"
INTRODUCTION TO WRITING FUNCTIONS IN R
Defining session()
session <- function() {
r_version <- [Link],
operating_system <- [Link]()[c("sysname", "release")],
loaded_pkgs <- loadedNamespaces()
# ???
}
INTRODUCTION TO WRITING FUNCTIONS IN R
Defining session()
session <- function() {
list(
r_version = [Link],
operating_system = [Link]()[c("sysname", "release")],
loaded_pkgs = loadedNamespaces()
)
}
INTRODUCTION TO WRITING FUNCTIONS IN R
Calling session()
session()
$r_version
[1] "R version 3.5.3 (2019-03-11)"
$operating_system
sysname release
"Linux" "4.14.106-79.86.amzn1.x86_64"
$loaded_pkgs
[1] "Rcpp" "grDevices" "crayon"
[4] "dplyr" "assertthat" "R6"
[7] "magrittr" "datasets" "pillar"
[10] "rlang" "utils" "praise"
[13] "rstudioapi" "graphics" "base"
[16] "tools" "glue" "purrr"
[19] "yaml" "compiler" "pkgconfig"
[22] "stats" "tidyselect" "methods"
[25] "tibble"
INTRODUCTION TO WRITING FUNCTIONS IN R
Multi-assignment
library(zeallot)
c(vrsn, os, pkgs) %<-% session()
vrsn
"R version 3.5.3 (2019-03-11)"
os
sysname release
"Linux" "4.14.106-79.86.amzn1.x86_64"
INTRODUCTION TO WRITING FUNCTIONS IN R
Attributes
month_no <- setNames(1:12, [Link]) attr(month_no, "names")
month_no
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul"
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec [8] "Aug" "Sep" "Oct" "Nov" "Dec"
1 2 3 4 5 6 7 8 9 10 11 12
attr(month_no, "names") <- [Link]
attributes(month_no) month_no
$names January February March April May
[1] "Jan" "Feb" "Mar" "Apr" "May" "Jun" "Jul" 1 2 3 4 5
[8] "Aug" "Sep" "Oct" "Nov" "Dec" June July August September October
6 7 8 9 10
November December
11 12
INTRODUCTION TO WRITING FUNCTIONS IN R
Attributes of a data frame
orange_trees attributes(orange_trees)
# A tibble: 35 x 3 $names
Tree age circumference [1] "Tree" "age"
<ord> <dbl> <dbl> [3] "circumference"
1 1 118 30
2 1 484 58 $[Link]
3 1 664 87 [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
4 1 1004 115 [16] 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
5 1 1231 120 [31] 31 32 33 34 35
6 1 1372 142
7 1 1582 145 $class
8 2 118 33 [1] "tbl_df" "tbl" "[Link]"
9 2 484 69
10 2 664 111
# … with 25 more rows
1 data(Orange, package = "datasets")
INTRODUCTION TO WRITING FUNCTIONS IN R
Attributes added by group_by()
library(dplyr) $names
orange_trees %>% [1] "Tree" "age" "circumference"
group_by(Tree) %>%
attributes() $[Link]
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
[19] 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
$class
[1] "grouped_df" "tbl_df" "tbl" "[Link]"
$groups
# A tibble: 5 x 2
Tree .rows
<ord> <list>
1 3 <int [7]>
2 1 <int [7]>
3 5 <int [7]>
4 2 <int [7]>
5 4 <int [7]>
INTRODUCTION TO WRITING FUNCTIONS IN R
When to use each technique
If you need the result to have a particular type, add additional return values as a ributes.
Otherwise, collect all return values into a list.
INTRODUCTION TO WRITING FUNCTIONS IN R
broom
Model objects are converted into 3 data frames.
function level example
glance() model degrees of freedom
tidy() coe cient p-values
augment() observation residuals
INTRODUCTION TO WRITING FUNCTIONS IN R
Let's practice!
INTRODUCTION TO WRITING FUNCTIONS IN R
Environments
INTRODUCTION TO WRITING FUNCTIONS IN R
Richie Co on
Curriculum Architect at DataCamp
Environments are like lists
datacamp_lst <- list( datacamp_env <- list2env(datacamp_lst)
name = "DataCamp",
founding_year = 2013,
website = "[Link]
)
[Link](datacamp_lst) [Link](datacamp_env)
founding_year : num 2013 founding_year : num 2013
name : chr "DataCamp" name : chr "DataCamp"
website : chr "[Link] website : chr "[Link]
INTRODUCTION TO WRITING FUNCTIONS IN R
Environments have parents
INTRODUCTION TO WRITING FUNCTIONS IN R
Getting the parent environment
parent <- [Link](datacamp_env) search()
environmentName(parent)
[1] ".GlobalEnv" "package:stats"
"R_GlobalEnv" [3] "package:graphics" "package:grDevices"
[5] "package:utils" "package:datasets"
[7] "package:methods" "Autoloads"
grandparent <- [Link](parent)
[9] "package:base"
environmentName(grandparent)
"package:stats"
INTRODUCTION TO WRITING FUNCTIONS IN R
Does a variable exist?
datacamp_lst <- list(
name = "DataCamp",
website = "[Link]
)
datacamp_env <- list2env(datacamp_lst)
founding_year <- 2013
exists("founding_year", envir = datacamp_env)
TRUE
exists("founding_year", envir = datacamp_env, inherits = FALSE)
FALSE
INTRODUCTION TO WRITING FUNCTIONS IN R
Let's practice!
INTRODUCTION TO WRITING FUNCTIONS IN R
Scope and
precedence
INTRODUCTION TO WRITING FUNCTIONS IN R
Richie Co on
Curriculum Architect at DataCamp
Accessing variables outside functions
x_times_y <- function(x) { x_times_y <- function(x) {
x * y x * y
} }
y <- 4
x_times_y(10)
x_times_y(10)
Error in x_times_y(10) :
object 'y' not found 40
INTRODUCTION TO WRITING FUNCTIONS IN R
Accessing function variables from outside
x_times_y <- function(x) {
x * y
}
y <- 4
x_times_y(10)
print(x)
Error in print(x) : object 'x' not found
INTRODUCTION TO WRITING FUNCTIONS IN R
What's best? Inside or outside?
x_times_y <- function(x) {
y <- 6
x * y
}
y <- 4
x_times_y(10)
60
INTRODUCTION TO WRITING FUNCTIONS IN R
Passed in vs. defined in
x_times_y <- function(x) {
x <- 9
y <- 6
x * y
}
y <- 4
x_times_y(10)
54
INTRODUCTION TO WRITING FUNCTIONS IN R
Let's practice!
INTRODUCTION TO WRITING FUNCTIONS IN R