Replacing for by Lapply function in R

4

This is my list

lista1<-list(c(1, 2, 3, 4, 5), c(6, 7, 8, 9, 10), c(11, 12, 13, 14, 15
), c(16, 17, 18, 19, 20), c(21, 22, 23, 24, 25))

I build a new list of the way below.

novalista <- vector(mode = "list", length=5)

for (i in 1:5) {
  for(k in 1:5) {     
    novalista[[i]][k] <- lista1[[i]][k]*8
  }
}

novalista

I've been wanting to make code simpler / cleaner using the lapply function. That is, I want to replace these two "for's" with the lapply function.

The difficulty is to use the function lapply with two different indices (i and k)

Any help?

    
asked by anonymous 27.08.2018 / 03:49

2 answers

4

First, R is a vectorized programming language. This means that the double for cycle is not necessary. Since each member of lista1 is a vector, we can multiply the integer vector by 8.

for (i in 1:5) {
    novalista[[i]] <- lista1[[i]]*8
}

And the code is already simpler and faster.

In the example of the question, you can do even better. What the question asks is to apply a function to each member of the lista1 list, or else that's exactly what lapply does. No need to index list members . Just apply the function directly to each of them. It is also necessary to take into account that lapply does not eliminate the cycle, lapply is also a cycle form.

novalista2 <- lapply(lista1, '*', 8)

identical(novalista, novalista2)
#[1] TRUE

Here the function is the multiplication, * , with the extra argument 8 , the multiplier.

This almost always gives simpler code, but unlike many R users, it's not always faster. To test this I will use the microbenchmark package. The two ways to create novalista are written in function form and then tested.

f <- function(lst){
    novalista <- vector(mode = "list", length=length(lst))
    for (i in seq_along(lst)) {
        novalista[[i]] <- lst[[i]]*8
    }
    novalista
}

g <- function(lst) lapply(lst, '*', 8)

First with the short list of the question.

microbenchmark::microbenchmark(f(lista1), g(lista1), times = 1e4)

Now with a large list.

lista2 <- lapply(1:1000, function(i) sample(1000, 100))
microbenchmark::microbenchmark(f(lista2), g(lista2))

As you can see, in both cases for was faster.

    
27.08.2018 / 04:42
1

Run:

lista1<-list(c(1, 2, 3, 4, 5), c(6, 7, 8, 9, 10), c(11, 12, 13, 14, 15
), c(16, 17, 18, 19, 20), c(21, 22, 23, 24, 25))

novalista<-lapply(lista1,'*',8)
novalista

#[[1]]
#[1]  8 16 24 32 40

#[[2]]
#[1] 48 56 64 72 80

#[[3]]
#[1]  88  96 104 112 120

#[[4]]
#[1] 128 136 144 152 160

#[[5]]
#[1] 168 176 184 192 200
    
27.08.2018 / 04:23