[英]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
鏈訪問深層嵌套列表的快捷方式。 在這個問題中, modify
比map
有優勢,因為它會保留輸入的類型,而不是將所有內容強制轉換為列表,如果您的列表結構具有向量元素,這可能是相關的。
使用給定的輸入(內部帶有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.