Comparison of the speed of if-else, ifelse(), and switch() statements, as well as indexing with [.
ifelse() and [-indexing are vectorized, so they can take vectors as inputs, but that isn't used here because the main purpose of these tests is to compare against if-else and switch() statements.
# ========================
library(microbenchmark)
library(plyr)
# Test functions
if2 <- function(dat) {
for (x in dat) {
if (x == "a") 1
else 2
}
}
if3 <- function(dat) {
for (x in dat) {
if (x == "a") 10
else if (x == "b") 20
else 30
}
}
if8 <- function(dat) {
for (x in dat) {
if (x == "a") 10
else if (x == "b") 20
else if (x == "c") 30
else if (x == "d") 40
else if (x == "e") 50
else if (x == "f") 60
else if (x == "g") 70
else 80
}
}
ifelse2 <- function(dat) {
for (x in dat) {
ifelse(x == "a", 10, 20)
}
}
switch2 <- function(dat) {
for (x in dat) switch(x, a=1, 2)
}
switch3 <- function(dat) {
for (x in dat) switch(x, a=1, b=2, 3)
}
switch8 <- function(dat) {
for (x in dat) switch(x, a=1, b=2, c=3, d=4, e=5, f=6, g=7, 8)
}
# These two functions aren't exactly the same as the above: there's no default
# case. Instead there's an `h` option. These are here for comparison.
index_dyn8 <- function(dat) {
# Create the index vector inside the loop
for (x in dat) c(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8)[x]
}
index_saved8 <- function(dat) {
# Create the index vector outside the loop
idx <- c(a=1, b=2, c=3, d=4, e=5, f=6, g=7, h=8)
for (x in dat) idx[x]
}
dat <- rep(letters[1:8], 1000)
num <- rep(1:8, 1000)
res <- microbenchmark(
if2(dat), if3(dat), if8(dat),
switch2(dat), switch3(dat), switch8(dat),
ifelse2(dat),
index_dyn8(dat),
index_dyn8(num),
index_saved8(dat),
index_saved8(num),
times = 20
)
# Summarize, convert to ms
res_summary <- ddply(res, c("expr"), summarise,
N=length(time)/1e6, m_time=mean(time)/1e6, sd=sd(time)/1e6, se=sd/sqrt(N))
# Mark those above the mean as outliers (we'll remove them for a later plot)
res_summary$outlier <- "Outlier"
res_summary$outlier[res_summary$m_time < mean(res_summary$m_time)] <- "Not outlier"
# Plot
library(ggplot2)
ggplot(res_summary, aes(x=expr, y=m_time, fill=outlier)) +
geom_bar(stat="identity", colour="black") +
scale_fill_manual(values = c("black", "#990000")) +
ylab("mean time (ms)") +
theme(axis.text.x = element_text(angle=70, hjust=1, size=12))
# Again, but without the outliers
res_summary2 <- subset(res_summary, m_time < mean(m_time))
ggplot(res_summary2, aes(x=expr, y=m_time)) + geom_bar(stat="identity") +
ylab("mean time (ms)") +
theme(axis.text.x = element_text(angle=70, hjust=1, size=12))