Search code examples
rpurrr

How can I select specific items in a list that are not at the top level?


I'm trying to select specific items in a list that are not in the top level, and everything I can think of doesn't work the way I would expect. Here is a dummy list where what I do NOT want is item "C":

MyList <- list("pine" = list(A = data.frame(), 
                             B = data.frame(), 
                             C = hist(rnorm(10))), 
               "fir" = list(A = data.frame(), 
                            B = data.frame(), 
                            C = hist(rnorm(10))), 
               "cedar" = list(A = data.frame(), 
                              B = data.frame(), 
                              C = hist(rnorm(10))))

If I only needed to go one level down, this is what I would do to get only "A" and "B":

MyList[["pine"]][c("A", "B")]

I thought that one of these two approaches would mimic that, but both give me errors:

NotC <- map(.x = MyList, 
        .f = \(x) map(x, .f = x[c("A", "B")]))

NotC <- lapply(MyList, \(x) lapply(x, \(y) y[c("A", "B")]))

It seems that R thinks I'm trying to select columns, because I'm getting errors such as "Error in `[.data.frame`(y, c("A", "B")) : undefined columns selected"


Solution

  • If it is always called "C" you can do this.

    MyList <- list("pine" = list(A = data.frame(), 
                                 B = data.frame(), 
                                 C = hist(rnorm(10))), 
                   "fir" = list(A = data.frame(), 
                                B = data.frame(), 
                                C = hist(rnorm(10))), 
                   "cedar" = list(A = data.frame(), 
                                  B = data.frame(), 
                                  C = hist(rnorm(10))))
    
    deletec <- function(l) {
      l[names(l) != "C"]
    }
    
    lapply(MyList, deletec)
    > $pine $pine$A data frame with 0 columns and 0 rows
    > 
    > $pine$B data frame with 0 columns and 0 rows
    > 
    > 
    > $fir $fir$A data frame with 0 columns and 0 rows
    > 
    > $fir$B data frame with 0 columns and 0 rows
    > 
    > 
    > $cedar $cedar$A data frame with 0 columns and 0 rows
    > 
    > $cedar$B data frame with 0 columns and 0 rows
    

    You could write it more compactly, but basically write a function that does what you want. Then lapply() that function.