Lapply Function /Loops on List of Lists R

lapply function /loops on list of lists R

We can loop through the list of list with a nested lapply/sapply

 lapply(data, sapply, mean)

It is otherwise written as

 lapply(data, function(x) sapply(x, mean))

Or if you need the output with the list structure, a nested lapply can be used

 lapply(data, lapply, mean)

Or with rapply, we can use the argument how to get what kind of output we want.

  rapply(data, mean, how='list')

If we are using a for loop, we may need to create an object to store the results.

  res <- vector('list', length(data))
for(i in seq_along(data)){
for(j in seq_along(data[[i]])){
res[[i]][[j]] <- mean(data[[i]][[j]])
}
}

Applying a loop to a list of lists in r

The problem here is that the data_to_add is empty. It is empty because listJii[[i]]$Date_record does not exist. Because a list of lists (i.e., a nested list) can be more confusing than a simple list or a data frame, you need to work through the layers of list structures (from outside in) to find the location of the vector that you seek. The Date_record in this case is in listJii[[i]][[j]].

How to build a nested loop to evaluate a vector in a nested list?

A trick to getting the nested loops correct is to work from the inside out.

Step 1. Make sure the core function works, without using loops.

Test the command line(s) with sample vectors in the nested list.

unique(listJii[[1]][[1]]$Date_record) # this is what you want to store in `data_to_add`

# you have two layers of lists in `listJii`, so you need two list layers in `data_to_add`
data_to_add <- list()
data_to_add[[1]] <- list()
data_to_add[[1]][[1]] <- unique(listJii[[1]][[1]]$Date_record)

# test
data_to_add # you needed all those commands above to make this work, so those will be necessary in your function

Step 2. Build your loops, one at a time, first by replacing the innermost variable that needs changing and then work your way out. Test it every step along the way.

## innermost loop test
data_to_add <- list()
data_to_add[[1]] <- list()
for(j in seq_along(listJii[[1]])) {
data_to_add[[1]][[j]] <- unique(listJii[[1]][[j]]$Date_record)
}

# test
data_to_add # the innermost loop works

## outer loop test
data_to_add <- list()
for(i in seq_along(listJii)) {
data_to_add[[i]] <- list()
for(j in seq_along(listJii[[i]])) {
data_to_add[[i]][[j]] <- unique(listJii[[i]][[j]]$Date_record)
}
}

# test
data_to_add # the final loop works--this function is now ready

Your listJsubs function works with the data_to_add built here. Though, because nested lists are used in your evaluation, you may want to consider using nested loops to follow through for listJsubs as well.

An alternative to using nested loops on nested lists is using nested lapply()

lapply() is another function that you can use instead of for-loops over a list.
Its output is a list, so you do not need to assign empty list structures beforehand to data_to_add and data_to_add[[i]] like the way you need for for-loops.

data_to_add <- lapply(listJii, function(i){
lapply(i, function(j){
return(unique(j$Date_record))
})
})

Note: the core function in this nested lapply() is a bit different from the one used in the nested for-loops. It's a different approach that I could do with lapply() and get the same results. I actually built it from outside in--hence, you don't see any i in the core function.

Apply function to a list of lists

you don't need for loops to do so. You can directly work with lapply:

lapply(dati_fault, \(x) colMeans(do.call(rbind, x)))

This does the following: for each entry of dati_fault (i.e. each sublist of 31 matrices) these matrices are bound together (using rbind) into one single matrix with 310 rows and 5 columns. Then, colMeans is applied to this matrix.

If you are not familiar with the shorthand notation for anonymous functions (i.e. \(x)) you can read about it here.

Loop over first list in a list of lists/nested list - R

You could use names() to extract the list names, and iterate them in the loop.

firms <- names(list)

for (firm in firms) {
Function(list[[firm]][2], list[[firm]][3])
}

Note that you cannot use list$firm in the for loop. The $ works only if list has an element named firm. In the loop you should use list[[firm]].

Using lapply or loop to create multiple figures from a list of lists of matricies

something like this (two nested loops):

for(i in 1:length(biglist)) {

sublist <- biglist[[i]]

for(j in 1:length(sublist)) {

plotdata <- sublist[[j]]
name <- paste(english::ordinal(j),letters[i],sep="_")

assign(name, ggplot(melt(as.data.table(plotdata)),
aes(x=variable,y=value))+
geom_boxplot()+ggtitle(name)+
ylab(names(sublist)[j]))

}

}

Lapplying a function over two lists of dataframes in R

Here, we could use Map from base R to apply the function on the corresponding elements of both the lists

out <- Map(my_function, list_A, list_B)

lapply can also be used, if we loop over the sequence of one of the list

out <- lapply(seq_along(list_A), function(i) 
my_function(list_A[[i]], list_B[[i]]))

which is similar to using a for loop

out <- vector('list', length(list_A))
for(i in seq_along(list_A)) out[[i]] <- my_function(list_A[[i]], list_B[[i]])

R: Apply function to nested lists

If your list structures match, as they do in your example, it may be simpler to unlist and then relist the data. First unlist the lon/lat data and cbind to make 2-column matrices:

library(geosphere)
p1 <- cbind(unlist(nested_lons1), unlist(nested_lats1))
p2 <- cbind(unlist(nested_lons2), unlist(nested_lats2))

Now compute the distances and convert back to a list of the same structure:

d12 <- distHaversine(p1, p2)
d12.lst <- relist(d12, nested_lons1)
str(d12.lst)
# List of 4
# $ :List of 3
# ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
# $ :List of 2
# ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
# $ :List of 1
# ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
# $ :List of 4
# ..$ : num [1:50] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:25] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:30] 0 0 0 0 0 0 0 0 0 0 ...
# ..$ : num [1:45] 0 0 0 0 0 0 0 0 0 0 ...

Of course, this only works if the four nested lists have the same structure.

How to apply a function to more than one list of lists in r?

We can just use rapply from base R which will recursively loop over the three nested list an get the max from the innervector

rapply(out, max)

If we want across max

library(dplyr)
library(data.table)
reshape2::melt(out) %>%
group_by(L3) %>%
summarise(value = max(value))
# A tibble: 2 x 2
# L3 value
# <int> <dbl>
#1 1 1.27
#2 2 1.27

Or it could be

flatten(out) %>% 
transpose %>%
map(reduce, pmax)
#[[1]]
# 1 2 3 4 5 6 7 8 9 10 11 12
#1.070 0.229 1.270 0.190 0.000 0.000 0.000 0.000 0.190 0.673 0.000 0.766

#[[2]]
# 1 2 3 4 5 6 7 8
#1.070 1.270 0.190 0.000 0.000 0.190 0.673 0.766

Or a single value

flatten(out) %>% 
transpose %>%
map_dbl(reduce, max)
#[1] 1.27 1.27


Related Topics



Leave a reply



Submit