Home > other >  Repeat triple nested lists based on length of matching column in R
Repeat triple nested lists based on length of matching column in R

Time:11-20

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 structure 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
  • Related