user00110014 user00110014 - 19 days ago 7
R Question

Calculate a function for each element of a matrix using another vector as input in R

I want to calculate the variables

fn_x
and
Fn_x
by avoiding the loop from the following codes:

y <- seq(0,2,0.01)
z <- sort(rexp(100,1))
U <- round(runif(100), 0)
myfun <- function(x) 0.75 * (1-x^2) * (abs(x)<1)

fn_x <- matrix(0, length(y), 1)
Fn_x <- matrix(0, length(y), 1)
for(j in 1:length(y)){
fn_x[j] <- (1/(100*2)) * sum(myfun((y[j]-z)/2))
Fn_x[j] <- (1/100)*sum(I(z <=y[j] & U==1))
}


My function is using two different matrices with different dimensions for calculating each element, so the function
apply
is not working in this case. Is it possible to solve this problem without using any package?

Answer

Since you're already preallocating vectors before executing the loop, you're doing a lot of the heavy lifting needed to speed up calculations. At this point, data.table or pure implementation in C++ using e.g. Rcpp package would boost the speed.

library(microbenchmark)

microbenchmark(
  original = {
    fn_x <- matrix(NA, length(y), 1)
    Fn_x <- matrix(NA, length(y), 1)
    for(j in 1:length(y)){
      fn_x[j] <- (1/(100*2)) * sum(myfun((y[j]-z)/2))
      Fn_x[j] <- (1/100)*sum(I(z <=y[j] & U==1))
    }
  },
  new =  {
    fn_x2 <- sapply(y, FUN = function(x, z) {
      (1/(100*2)) * sum(myfun((x-z)/2))
    }, z = z)

    Fn_x2 <- sapply(y, FUN = function(x, z, U) {
      (1/100) * sum(I(z <= x & U == 1))
    }, z = z, U = U)
  }
)

Unit: milliseconds
     expr      min        lq     mean    median       uq      max
 original 9.550934 10.407091 12.13302 10.895803 11.95638 22.87758
      new 8.734813  9.126127 11.18128  9.264137 10.12684 87.68265