简体   繁体   中英

Remove element from list of lists in R

This seems to a variation on many topics on SE, but I haven't seen one specifically addressing the problem I'm having. I have a list of lists:

mylist <- list(list(`1` = 2:3, `2` = 4:5, `3` = 6:7, `4` = 8:10), list(
    `1` = 11:12, `2` = 13:14, `3` = 15:16, `4` = 17:18, `5` = 19:20, 
    `6` = 21:22), list(`1` = 23:24))

I would like to remove any subelements in the inner level that are contained in some other vector. For example if the elements to be removed are c(4,5,19,20,23,24) , then I would expect the output:

list(list(`1` = 2:3, `3` = 6:7, `4` = 8:10), list(
    `1` = 11:12, `2` = 13:14, `3` = 15:16, `4` = 17:18, 
    `6` = 21:22))

Removing the names would be ok as well. I've tried many things including:

removeListElem <- function(inlist,elem_remove){
  lapply(inlist,setdiff,elem_remove)
}

lapply(mylist,function(x) removeListElem(x,c(4,5,19,20,23,24)))

But it produces the output

list(list(`1` = 2:3, `2` = integer(0), `3` = 6:7, `4` = 8:10), 
    list(`1` = 11:12, `2` = 13:14, `3` = 15:16, `4` = 17:18, 
        `5` = integer(0), `6` = 21:22), list(`1` = integer(0)))

which I can then filter out for integer(0) .

Is there a clean and efficient (not doing nested lapply's) solution to removing a given set of elements in a list of lists?

We can incorporate the clean-up of inner lists into your function:

removeListElem <- function(inlist,elem_remove){
  outlist = lapply(inlist,setdiff,elem_remove)
  outlist[lengths(outlist) > 0]
}

This takes care of the integer(0) s, but still gives an empty list in the result:

result = lapply(mylist,function(x) removeListElem(x,c(4,5,19,20,23,24)))
result
# [[1]]
# [[1]]$`1`
# [1] 2 3
# 
# [[1]]$`3`
# [1] 6 7
# 
# [[1]]$`4`
# [1]  8  9 10
# 
# 
# [[2]]
# [[2]]$`1`
# [1] 11 12
# 
# [[2]]$`2`
# [1] 13 14
# 
# [[2]]$`3`
# [1] 15 16
# 
# [[2]]$`4`
# [1] 17 18
# 
# [[2]]$`6`
# [1] 21 22
# 
# 
# [[3]]
# named list()

So we can clean up the result in a similar way:

result[lengths(result) > 0]
# [[1]]
# [[1]]$`1`
# [1] 2 3
# 
# [[1]]$`3`
# [1] 6 7
# 
# [[1]]$`4`
# [1]  8  9 10
# 
# 
# [[2]]
# [[2]]$`1`
# [1] 11 12
# 
# [[2]]$`2`
# [1] 13 14
# 
# [[2]]$`3`
# [1] 15 16
# 
# [[2]]$`4`
# [1] 17 18
# 
# [[2]]$`6`
# [1] 21 22

This uses a nested lapply , just like your attempt. We can, of course, package it all into a function:

removeListElemComplete = function(inlist, elem_remove) {
  outlist = lapply(inlist, removeListElem, elem_remove = elem_remove)
  outlist[lengths(outlist) > 0]
}

removeListElemComplete(mylist, c(4,5,19,20,23,24))
# [[1]]
# [[1]]$`1`
# [1] 2 3
# 
# [[1]]$`3`
# [1] 6 7
# 
# [[1]]$`4`
# [1]  8  9 10
# 
# 
# [[2]]
# [[2]]$`1`
# [1] 11 12
# 
# [[2]]$`2`
# [1] 13 14
# 
# [[2]]$`3`
# [1] 15 16
# 
# [[2]]$`4`
# [1] 17 18
# 
# [[2]]$`6`
# [1] 21 22

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM