I would like to duplicate/repeat triple nested lists based on the number of rows matching the same name in a data frame.
Here is a triple nested list:
list.A <- list(a = c(1,2,5,6), b = c(2,4,6,5), c = c(2,4,2,5))
list.B <- list(a = c(7,7,7,7), b = c(8,8,8,8), c = c(9,9,9,9))
weights <- list(list.A, list.B)
names(weights) <- c("list.A", "list.B")
list.A <- list(a = c(2,2,2,2), b = c(3,3,3,3), c = c(4,4,4,4))
list.B <- list(a = c(5,5,5,5), b = c(6,6,6,6), c = c(7,7,7,7))
scores <- list(list.A, list.B)
names(scores) <- c("list.A", "list.B")
megalist <- list(weights, scores)
names(megalist) <- c("weights", "scores")
megalist
> megalist
$weights
$weights$list.A
$weights$list.A$a
[1] 1 2 5 6
$weights$list.A$b
[1] 2 4 6 5
$weights$list.A$c
[1] 2 4 2 5
$weights$list.B
$weights$list.B$a
[1] 7 7 7 7
$weights$list.B$b
[1] 8 8 8 8
$weights$list.B$c
[1] 9 9 9 9
$scores
$scores$list.A
$scores$list.A$a
[1] 2 2 2 2
$scores$list.A$b
[1] 3 3 3 3
$scores$list.A$c
[1] 4 4 4 4
$scores$list.B
$scores$list.B$a
[1] 5 5 5 5
$scores$list.B$b
[1] 6 6 6 6
$scores$list.B$c
[1] 7 7 7 7
Here is my dataframe that I want to use to dictate the number of repeated lists:
mydf <- as.data.frame(c("a", "a", "a", "b", "b", "c"))
colnames(mydf) <- "Freq"
> mydf
Freq
1 a
2 a
3 a
4 b
5 b
6 c
I would like this output where from megalist[["list.A"]]
list a
is repeated 3 times because it has 3 rows in mydf, b
is repeated 2 times because it has the next 2 rows in mydf, and c
is repeated 1 time because it has the next 1 row in mydf:
> megalist
$weights
$weights$list.A
$weights$list.A$a
[1] 1 2 5 6
$weights$list.A$a
[1] 1 2 5 6
$weights$list.A$a
[1] 1 2 5 6
$weights$list.A$b
[1] 2 4 6 5
$weights$list.A$b
[1] 2 4 6 5
$weights$list.A$c
[1] 2 4 2 5
$weights$list.B
$weights$list.B$a
[1] 7 7 7 7
$weights$list.B$b
[1] 8 8 8 8
$weights$list.B$c
[1] 9 9 9 9
$scores
$scores$list.A
$scores$list.A$a
[1] 2 2 2 2
$scores$list.A$a
[1] 2 2 2 2
$scores$list.A$a
[1] 2 2 2 2
$scores$list.A$b
[1] 3 3 3 3
$scores$list.A$b
[1] 3 3 3 3
$scores$list.A$c
[1] 4 4 4 4
$scores$list.B
$scores$list.B$a
[1] 5 5 5 5
$scores$list.B$b
[1] 6 6 6 6
$scores$list.B$c
[1] 7 7 7 7
I have tried:
megalist.repeated <- lapply(megalist, function(x, new) {
x[["list.A"]][new]
}, new = mydf$Freq)
but this gets rid of list.B
, and I want to keep everything else the same and change only list.A
.
I have also tried:
megalist.repeated <- lapply(megalist, function(x, y)
if(x[["y"]]=="list.A")
lapply(y, function (y, new) {
y[new]
}, new = mydf$Freq
) else y)
but my if
statement returns a length of zero.
CodePudding user response:
Loop over the nested list
with lapply
, then extract ([[
) the 'list.A' element with a lambda function, use the mydf$Freq
to replicate the named inner list of list.A
, assign (<-
) back to the same element to update, and return the whole object x
megalist2 <- lapply(megalist, \(x) {
x[["list.A"]] <- x[["list.A"]][mydf$Freq]
x})
-checking the str
ucture of old vs new object
> str(megalist2)
List of 2
$ weights:List of 2
..$ list.A:List of 6
.. ..$ a: num [1:4] 1 2 5 6
.. ..$ a: num [1:4] 1 2 5 6
.. ..$ a: num [1:4] 1 2 5 6
.. ..$ b: num [1:4] 2 4 6 5
.. ..$ b: num [1:4] 2 4 6 5
.. ..$ c: num [1:4] 2 4 2 5
..$ list.B:List of 3
.. ..$ a: num [1:4] 7 7 7 7
.. ..$ b: num [1:4] 8 8 8 8
.. ..$ c: num [1:4] 9 9 9 9
$ scores :List of 2
..$ list.A:List of 6
.. ..$ a: num [1:4] 2 2 2 2
.. ..$ a: num [1:4] 2 2 2 2
.. ..$ a: num [1:4] 2 2 2 2
.. ..$ b: num [1:4] 3 3 3 3
.. ..$ b: num [1:4] 3 3 3 3
.. ..$ c: num [1:4] 4 4 4 4
..$ list.B:List of 3
.. ..$ a: num [1:4] 5 5 5 5
.. ..$ b: num [1:4] 6 6 6 6
.. ..$ c: num [1:4] 7 7 7 7
> str(megalist)
List of 2
$ weights:List of 2
..$ list.A:List of 3
.. ..$ a: num [1:4] 1 2 5 6
.. ..$ b: num [1:4] 2 4 6 5
.. ..$ c: num [1:4] 2 4 2 5
..$ list.B:List of 3
.. ..$ a: num [1:4] 7 7 7 7
.. ..$ b: num [1:4] 8 8 8 8
.. ..$ c: num [1:4] 9 9 9 9
$ scores :List of 2
..$ list.A:List of 3
.. ..$ a: num [1:4] 2 2 2 2
.. ..$ b: num [1:4] 3 3 3 3
.. ..$ c: num [1:4] 4 4 4 4
..$ list.B:List of 3
.. ..$ a: num [1:4] 5 5 5 5
.. ..$ b: num [1:4] 6 6 6 6
.. ..$ c: num [1:4] 7 7 7 7