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/

Lingyun Zhang (张凌云)
Lingyun Zhang (张凌云)
Design Analyst

I have research interests in Statistics, applied probability and computation.