A Case Study On Efficiency
Introduction
For solving a bigger problem, I need to deal with the following problem: We have a matrix—it is called target matrix, e.g.
$$ T = \left(t_{ij}\right)_{n\times n}, $$
where $t_{ij}=1$ for $1\le i,\ j\le n$; we have another matrix---it is called *position matrix*,$$ P = \left(p_{ij}\right)_{n\times m}, $$
where $1\le m < n$ and $1\le p_{ij}\le n$. We want to change some of $t_{ij}$ to $-1$, and $p_{ij}$ tells which elements in $T$ to be changed. For example, if $p_{1,\ 2}=5$, which means that $t_{1,\ 5}$ will be changed to $-1$.I write two R functions; they both can do the task of changing part of the target matrix. In the first R function, I use for
loop; in the second R function, I don’t.
The purpose of this note is to compare efficiency of the two functions.
R code
# Function 1
change_part_of_matrix_1 <- function(target_m,
position_m,
a_value)
{the_dim <- dim(target_m)
row_nbr <- the_dim[1]
for(i in 1:row_nbr) {
target_m[i, position_m[i, ]] <- a_value
}
return(target_m)
}
# Function 2
change_part_of_matrix_2 <- function(target_m,
position_m,
a_value)
{the_dim <- dim(target_m)
row_nbr <- the_dim[1]
col_nbr <- the_dim[2]
the_vec <- as.vector(target_m)
the_positions <- as.vector((position_m - 1) * row_nbr + 1:row_nbr)
the_vec[the_positions] <- a_value
re_m <- matrix(the_vec, ncol = col_nbr, nrow = row_nbr)
return(re_m)
}
Comparing Efficiency
In [1], the authors talk about two kinds of efficiency, i.e. coder’s efficiency and code’s efficiency. It took me a minute to write change_part_of_matrix_1
, and it took me about ten minutes to write change_part_of_matrix_2
. Next we compare code’s efficiency.
set.seed(12345)
tester <- function(n, my_func)
{t_m <- matrix(1, ncol = n, nrow = n)
p_m <- matrix(sample(1:n, 2*n, replace = TRUE),
nrow = n, ncol = 2, byrow = TRUE)
system.time({
my_func(t_m, p_m, -1)
})
}
# testing
tester(10, change_part_of_matrix_1)
## user system elapsed
## 0.04 0.00 0.03
tester(10, change_part_of_matrix_2)
## user system elapsed
## 0 0 0
tester(100, change_part_of_matrix_1)
## user system elapsed
## 0 0 0
tester(100, change_part_of_matrix_2)
## user system elapsed
## 0 0 0
tester(1000, change_part_of_matrix_1)
## user system elapsed
## 0 0 0
tester(1000, change_part_of_matrix_2)
## user system elapsed
## 0.02 0.00 0.02
Conclusion
The for
loop can be efficient in some situations.
References
[1] Colin Gillespie, C.; Lovelace, R. (2021). Efficient R programming. URL: https://csgillespie.github.io/efficientR/