簡體   English   中英

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

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

我怎樣才能從

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))))

到沒有作為數據框的“c3”元素的列表?

最好以tidyverse友好的方式或我可以放在管道中間的東西。

我已經嘗試過 list.remove、nested lapply、rapply、Filter,但似乎無法讓它們工作......而且我不想取消我的嵌套列表結構。

(編輯:抱歉,我在原始問題中的示例數據中有一個錯字(見下文),但如果您的解決方案在兩種情況下都適用,那就太好了!)

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)))))

這是使用modify_depth的正確場景,它用作modify鏈訪問深層嵌套列表的快捷方式。 在這個問題中, modifymap有優勢,因為它會保留輸入的類型,而不是將所有內容強制轉換為列表,如果您的列表結構具有向量元素,這可能是相關的。

使用給定的輸入(內部帶有p3元素而不是與p2處於同一級別),第二和第三級別的數據幀元素將被discard ,如下所示。 為了搜索嵌套列表的所有級別,我們可以設置一個while循環來遍歷這些級別,並在執行過程中丟棄數據幀。 我們需要.ragged = TRUE來處理列表深度的錯誤。 此版本自下而上搜索,但您也可以將其更改為自上而下搜索。

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

reprex 包(v0.2.1) 於 2019 年 2 月 20 日創建

您可以編寫自己的函數來執行此操作:

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))))

這也是 vecotized,因為它可以丟棄您需要的所有內容。 例如嘗試check(x,c('c1','c3'))

這是在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