Home > Back-end >  For loop and lapply
For loop and lapply

Time:09-22

First, I used a for loop for a vector of numbers, it worked well.

When I used lapply fucntion, the results was not I want. I only want one element within a list.

This is my example

# With for loop, the outcome is one vector of numbers
x <- c(0.2,0.5,0.03,0.006,0.08)
p.value <- NULL
for (i in 1:length(x)){
if(x[i] > 0.5 p.value[i] <- (1-x[i])*2
else p.value[i] <- x[i]*2

# with lapply
lapply(x, function(x) {if(x > 0.5) p.value <- (1-x)*2 else p.value <- x*2

The outcome from lapply is the combination of same results. I kinda realizing the problem, but I dont know how to change my code. Any suggestions for this?

CodePudding user response:

This can be solved in a vectorized way so you don't need a for loop or lapply.

p.value <- ifelse(x > 0.5, (1 - x), x) * 2

The lapply code does give me the expected output as for loop but you can change few things.

  • Use sapply since the output is a vector
  • assign p.value outside sapply and not inside the function.
  • Since you already have a vector named x, change the variable in anonymous function to another name.
p.value <- sapply(x, function(y) if(y > 0.5) (1-y)*2 else y*2)

CodePudding user response:

You may use replace which is faster than ifelse.

replace(x, x > .5, 1 - x)*2
# [1] 0.400 1.000 0.060 0.012 0.160

Benchmark

x <- sample(x, 1e6, replace=T)
microbenchmark::microbenchmark(ifelse=ifelse(x > 0.5, (1 - x), x) * 2,
                               replace=replace(x, x > .5, 1 - x)*2)
# Unit: milliseconds
#    expr       min       lq     mean   median       uq      max neval cld
#  ifelse 25.049546 31.29303 39.53500 36.23981 42.06574 124.9903   100   b
# replace  8.074329 11.06676 18.68296 14.02976 16.99336 100.2051   100  a 

CodePudding user response:

try sapply instead of lapply. that simplify list solution

  • Related