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 list
s
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
How to Get the Most Frequent Level of a Categorical Variable in R
Hashtag Extract Function in R Programming
How and When Should I Use On.Exit
Quickly Remove Zero Variance Variables from a Data.Frame
Grid Line Consistent with Ticks on Axis
Findinterval() with Right-Closed Intervals
How to Get Rows, by Group, of Data Frame with Earliest Timestamp
R Cmd Check Note: Found No Calls To: 'R_Registerroutines', 'R_Usedynamicsymbols'
How to Create Textarea as Input in a Shiny Webapp in R
Plotting the Average Values for Each Level in Ggplot2
Ggplot2: Define Plot Layout with Grid.Arrange() as Argument of Do.Call()