Electrino
Electrino

Reputation: 2900

Extract a vector from nested lists in R

I am trying to extract a vector from a nested list based on the value of another variable\element within the same nested list. Hopefully my example will explain what I'm trying to do.

To begin, I have a list of lists like so:

## Create the inner lists
# Inner list 1
listInner1 <- list(
  value = c(0.25),
  index = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
  left  = c(),
  right = c()
)

listInner1$left$index  <- c(1, 2, 3, 4, 5)
listInner1$left$good   <- TRUE
listInner1$right$index <- c(6, 7, 8, 8, 10)
listInner1$right$good  <- TRUE

# Inner list 2
listInner2 <- list(
  value = c(1.5),
  index = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
  left  = c(),
  right = c()
)

listInner2$left$index  <- c(1, 2, 3)
listInner2$left$good   <- TRUE
listInner2$right$index <- c(4, 5, 6, 7, 8, 9, 10)
listInner2$right$good  <- TRUE

# Inner list 3
listInner3 <- list(
  value = c(0.5),
  index = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10),
  left  = c(),
  right = c()
)

listInner3$left$index  <- c(1, 2, 3, 4, 5)
listInner3$right$index <- c( 6, 7, 8, 9, 10)
listInner3$left$left$index  <- c(2, 4, 6, 8, 10)
listInner3$left$right$index <- c(1, 3, 5 ,7, 9)
listInner3$left$left$good <- TRUE
listInner3$left$right$good <- TRUE


# put all inner lists into single list object
listMiddle <- list(listInner1, listInner2, listInner3)

# one more list for fun
listMaster <- list(listMiddle)

As you can see, some of the left and right elements of the nested lists contain the element good = TRUE and some don't.

What I'm trying to do is if a particular nested list contains the element good = TRUE then to extract the element index from that same nested list.

For example, manually creating my desired output for the above example would look something like this:

ans <- list(
  index.1 = c(1, 2, 3, 4, 5),
  index.2 = c(6, 7, 8, 8, 10),
  index.3 = c(1, 2, 3),
  index.4 = c(4, 5, 6, 7, 8, 9, 10),
  index.5 = c(2, 4, 6, 8, 10),
  index.6 = c(1, 3, 5 ,7, 9)
)

The object ans contains all the index vectors that are contained within a nested list that also contains good = TRUE.

Any suggestions as to how I could do this?

Upvotes: 4

Views: 670

Answers (1)

akrun
akrun

Reputation: 887841

Here is an option where we bind the nested elements to a more easily approachable format with rrapply, then, we get the index of 'good' columns, extract the corresponding 'index' elements from that position index by looping over in map2 (based on the the TRUE values), transpose the list , keep only the elements having greater than 0 length, flatten the list and set the names (if needed)

library(purrr)
library(rrapply)
library(stringr)
library(dplyr)
out <- rrapply(listMaster, how = 'bind')
i1 <- grep('good', names(out))
map2(out[i1-1], out[i1], `[`) %>%
   transpose %>%
   map( ~ keep(.x, lengths(.x) > 0)) %>%
   flatten %>%
   setNames(str_c('index.', seq_along(.)))

-output

$index.1
[1] 1 2 3 4 5

$index.2
[1]  6  7  8  8 10

$index.3
[1] 1 2 3

$index.4
[1]  4  5  6  7  8  9 10

$index.5
[1]  2  4  6  8 10

$index.6
[1] 1 3 5 7 9

Upvotes: 4

Related Questions