简体   繁体   English

如何删除嵌套列表列表中的元素?

[英]how to remove elements in list of lists of nested lists?

How can I go from我怎样才能从

x <- list(p1 = list(type='A',score=list(c1=10,c2=8,c3=data.frame(a=1, b=3, c=5))),
       p2 = list(type='B',score=list(c1=9,c2=9,c3=data.frame(a=2, b=2))),
       p3 = list(type='B',score=list(c1=9,c2=7,c3=data.frame(a=2, b=2))))

to a list without the "c3" elements that are data frames?到没有作为数据框的“c3”元素的列表?

Preferably in a tidyverse -friendly way or something I can put in the middle of a pipeline.最好以tidyverse友好的方式或我可以放在管道中间的东西。

I've already tried list.remove, nested lapply, rapply, Filter, but can't seem to get them to work... and I don't want to unlist my nested list structure.我已经尝试过 list.remove、nested lapply、rapply、Filter,但似乎无法让它们工作......而且我不想取消我的嵌套列表结构。

(Edit: sorry, I had a typo in the sample data in my original question (see below), but great if your solution works in both cases!) (编辑:抱歉,我在原始问题中的示例数据中有一个错字(见下文),但如果您的解决方案在两种情况下都适用,那就太好了!)

x <- list(p1 = list(type='A',score=list(c1=10,c2=8,c3=data.frame(a=1, b=3, c=5))),
       p2 = list(type='B',score=list(c1=9,c2=9,c3=data.frame(a=2, b=2)),
       p3 = list(type='B',score=list(c1=9,c2=7,c3=data.frame(a=2, b=2)))))

This is the right scenario to use modify_depth , which functions as a shortcut for chains of modify to access deep nested lists.这是使用modify_depth的正确场景,它用作modify链访问深层嵌套列表的快捷方式。 modify has an advantage over map in this problem because it will preserve the type of the input instead of coercing everything to lists, which may be relevant if you have vector elements of your list structure.在这个问题中, modifymap有优势,因为它会保留输入的类型,而不是将所有内容强制转换为列表,如果您的列表结构具有向量元素,这可能是相关的。

Using your given input (with a p3 element inside rather than on the same level as p2 ), the dataframe elements at the second and third levels are discard ed as below.使用给定的输入(内部带有p3元素而不是与p2处于同一级别),第二和第三级别的数据帧元素将被discard ,如下所示。 In order to search all levels of the nested list, we can set up a while loop to iterate through the levels, discarding dataframes as we go.为了搜索嵌套列表的所有级别,我们可以设置一个while循环来遍历这些级别,并在执行过程中丢弃数据帧。 We need .ragged = TRUE to deal with errors with list depth.我们需要.ragged = TRUE来处理列表深度的错误。 This version searches bottom up but you could change it to search top down as well.此版本自下而上搜索,但您也可以将其更改为自上而下搜索。

library(tidyverse)
x <- list(
  p1 = list(type = "A", score = list(c1 = 10, c2 = 8, c3 = data.frame(a = 1, b = 3, c = 5))),
  p2 = list(
    type = "B", score = list(c1 = 9, c2 = 9, c3 = data.frame(a = 2, b = 2)),
    p3 = list(type = "B", score = list(c1 = 9, c2 = 7, c3 = data.frame(a = 2, b = 2)))
  )
)

remove_dataframes <- function(input_list) {
  current_list <- input_list
  current_depth <- vec_depth(current_list)
  # current_depth <- max_depth
  while (current_depth > 1) {
    current_list <- modify_depth(
      .x = current_list,
      .depth = current_depth,
      .f = ~ discard(., is.data.frame),
      .ragged = TRUE
    )
  current_depth <- current_depth - 1
  }
  return(current_list)
}

x %>%
  remove_dataframes %>%
  glimpse
#> List of 2
#>  $ p1:List of 2
#>   ..$ type : chr "A"
#>   ..$ score:List of 2
#>   .. ..$ c1: num 10
#>   .. ..$ c2: num 8
#>  $ p2:List of 3
#>   ..$ type : chr "B"
#>   ..$ score:List of 2
#>   .. ..$ c1: num 9
#>   .. ..$ c2: num 9
#>   ..$ p3   :List of 2
#>   .. ..$ type : chr "B"
#>   .. ..$ score:List of 2

Created on 2019-02-20 by the reprex package (v0.2.1)reprex 包(v0.2.1) 于 2019 年 2 月 20 日创建

You can write your own function to do this:您可以编写自己的函数来执行此操作:

check = function(x,name){
  m = names(x)%in% name
  x = if(any(m)) x[!m] else x
  if(is.list(x)) sapply(x,check,name)
  else x
}

dput(check(x,'c3'))
list(p1 = list(type = "A", score = list(c1 = 10, c2 = 8)), p2 = list(
    type = "B", score = list(c1 = 9, c2 = 9), p3 = list(type = "B", 
        score = list(c1 = 9, c2 = 7))))

This is also vecotized in that it can discard all that you need.这也是 vecotized,因为它可以丢弃您需要的所有内容。 eg try check(x,c('c1','c3'))例如尝试check(x,c('c1','c3'))

Here is another alternative using rrapply() in the rrapply -package that works for arbitrary levels of nesting:这是在rrapply使用rrapply()另一种替代方法,适用于任意级别的嵌套:

library(rrapply)

x1 <- rrapply(x, condition = function(x, .xparents) !any(.xparents == "c3"), how = "prune")
str(x1)  
#> List of 3
#>  $ p1:List of 2
#>   ..$ type : chr "A"
#>   ..$ score:List of 2
#>   .. ..$ c1: num 10
#>   .. ..$ c2: num 8
#>  $ p2:List of 2
#>   ..$ type : chr "B"
#>   ..$ score:List of 2
#>   .. ..$ c1: num 9
#>   .. ..$ c2: num 9
#>  $ p3:List of 2
#>   ..$ type : chr "B"
#>   ..$ score:List of 2
#>   .. ..$ c1: num 9
#>   .. ..$ c2: num 7

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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