2 Functions
2 Functions
Hadley Wickham
Chief Scientist
RStudio
May 2015
1. What is a function?
# An infix function
`%+%` <- function(a, b) {
paste0(a, b)
}
"this" %+% " makes" %+% " one string"
Your turn
• Maintainable
• Fast
http://adv-r.had.co.nz/Exceptions-Debugging.html
Testing
browser()
options(error = recover)
options(error = NULL)
debugonce(f)
setBreakpoint(...)
# RStudio: breakpoints
stop("This is an error!")
Step into
Step out of
f <- function() g()
g <- function() h()
h <- function() i()
i <- function() j()
j <- function() stop("Error!")
f()
h <- function() {
x <- 2
y <- 3
browser()
i()
}
f()
f <- function() g()
g <- function() h()
h <- function() i()
i <- function() j()
j <- function() stop("Error!")
options(error = recover)
j()
options(error = NULL)
# In batch R process ----
dump_and_quit <- function() {
# Save debugging info to file last.dump.rda
dump.frames(to.file = TRUE)
# Quit R with error status
q(status = 1)
}
options(error = dump_and_quit)
data.frame(lapply(numeric_cols, mean))
}
col_means(mtcars)
col_means(mtcars[, 0])
col_means(mtcars[0, ])
col_means(mtcars[, "mpg", drop = F])
col_means(1:10)
col_means(as.matrix(mtcars))
col_means(as.list(mtcars))
data.frame(lapply(numeric_cols, mean))
}
Maintainable
code
http://adv-r.had.co.nz/Style.html
Tips
i <- 1
out <- numeric(length(x))
out[1] <- i
for (j in 2:length(x)) {
if (x[j] != x[j - 1]) {
i <- i + 1
}
out[j] <- i
}
out
Very terse, but once you
get the idea, expressive
# Too clever?
cumsum(c(TRUE, diff(x) != 0))
# Just right?
library(dplyr)
changed <- x != lag(x, default = !x[1])
cumsum(changed)
Tips
• Rewrite important code - your first
attempt will not usually be the best
approach.
Speed it up.
http://adv-r.had.co.nz/Profiling.html
What’s slow?
Profiling
• R has a sampling profiler that stops
execution every few ms and records the
functions currently being run
• Still experimental:
install_github("hadley/lineprof")
library(lineprof)
f <- function() {
pause(0.1)
g()
h()
}
g <- function() {
pause(0.1)
h()
}
h <- function() {
pause(0.1)
}
library(lineprof)
l
shine(l)
How can you make it
faster?
Speeding up code
• Look for existing solutions
• Do less
• Vectorise
• Parallelise
• Avoid copies
library(microbenchmark)
x <- runif(100)
microbenchmark(
sqrt(x),
x ^ 0.5,
exp(log(x) / 2)
)
Your turn
microbenchmark(
mtcars["Volvo 142E", "carb"],
mtcars[32, 11],
mtcars[[c(11, 32)]],
mtcars[["carb"]][32],
mtcars[[11]][32],
mtcars$carb[32],
.subset2(mtcars, 11)[32]
)
Caution