Reputation: 127
Here is an example (with dummy numbers) of a nested list with three levels:
mylist <- list("A" = list("A1" = list("1", "2", "3"),
"A2" = list("10", "20", "30")),
"B" = list("B1" = list("11", "22", "33"),
"B2" = list("110", "220", "330")))
I would like to extract the last element of each sublist (at the lower level) to a dataframe, to wrangle more easily with the data and do further calculations. The output would look like something like that:
> mylist
First_level Second_level Last_value
> A A1 3
> A A2 30
> B B1 33
> B B2 330
Here is a potential dataframe structure to receive the output.
df <- data.frame(First_level = character(),
Second_level = character(),
Last_value = integer())
I have tried a for loop:
for (i in length(mylist)){
for (j in length(mylist[[i]])){
df$last_element <- tail(mylist[[i]][[j]], 1)
}
}
df
But I must be too ignorant about nested lists to write correctly a double for loop to achieve this... Could you help?
Upvotes: 3
Views: 850
Reputation: 5232
With tidyverse
packages:
library(tidyverse)
map(mylist, ~map(.x, tail, 1)) %>%
unlist() %>%
as.list() %>%
as_tibble() %>%
pivot_longer(cols = everything()) %>%
separate(col = "name", sep = "\\.", into = c("first_level", "second_level"))
# A tibble: 4 x 3
first_level second_level value
<chr> <chr> <chr>
1 A A1 3
2 A A2 30
3 B B1 33
4 B B2 330
Upvotes: 2
Reputation: 887118
We could use rrapply
with melt
library(rrapply)
library(dplyr)
rrapply(mylist, how = 'melt') %>%
group_by(First_level = L1, Second_level = L2) %>%
summarise(Last_value = last(value), .groups = 'drop')
# A tibble: 4 x 3
# Groups: First_level [2]
# First_level Second_level Last_value
# <chr> <chr> <chr>
#1 A A1 3
#2 A A2 30
#3 B B1 33
#4 B B2 330
In the OP's loop, it is looping over a single value i.e. the length
instead it would be 1:length
or seq_along
out <- list()
for(i in seq_along(mylist)) {
for(j in seq_along(mylist[[i]])) {
out <- c(out, tail(mylist[[i]][[j]], 1))
}
}
Upvotes: 3