我将如何编写 purrr::keep 的递归版本?
How would I write a recursive version of purrr::keep?
假设我有一个嵌套列表,其中包含一堆不同级别的数据框。我想提取仅数据帧的扁平化列表。我如何使用 purrr
函数编写此代码?我应该看看 reduce
吗?
例如,给定数据:
s <- list(x = 1:10,
data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
report = list(A = data.frame(x = 1:3, y = c(2, 4, 6)),
B = data.frame(x = 1:3, y = c(3, 6, 9)),
z = 4:10,
other = data.frame(w = 3:5,
color = c("red", "green", "blue"))))
我想要 return:
的功能
list(data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
`report$A` = data.frame(x = 1:3, y = c(2, 4, 6)),
`report$B` = data.frame(x = 1:3, y = c(3, 6, 9)),
`report$other` = data.frame(w = 3:5,
color = c("red", "green", "blue")))
我写了一个递归函数:
recursive_keep <- function(.x, .f) {
loop <- function(.y) {
if(is.list(.y)) {
c(keep(.y, .f), flatten(map(discard(.y, .f), loop)))
} else if(.f(.y)) {
.y
} else {
NULL
}
}
loop(.x)
}
可以这样称呼:
recursive_keep(s, is.data.frame)
它似乎适用于此示例,但它不保留名称信息。我希望保留足够的信息,以便我可以从原始对象中提取数据。也许这是一个更容易回答的问题?
这个单行函数体的递归函数保留名称并且不使用包:
rec <- function(x, FUN = is.data.frame)
if (FUN(x)) list(x) else if (is.list(x)) do.call("c", lapply(x, rec, FUN))
str(rec(s)) # test
给予(输出后续):
List of 4
$ data :'data.frame': 5 obs. of 2 variables:
..$ report: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
..$ value : num [1:5] 29.1 19.9 21.2 13 25.2
$ report.A :'data.frame': 3 obs. of 2 variables:
..$ x: int [1:3] 1 2 3
..$ y: num [1:3] 2 4 6
$ report.B :'data.frame': 3 obs. of 2 variables:
..$ x: int [1:3] 1 2 3
..$ y: num [1:3] 3 6 9
$ report.other:'data.frame': 3 obs. of 2 variables:
..$ w : int [1:3] 3 4 5
..$ color: Factor w/ 3 levels "blue","green",..: 3 2 1
关于从 report
中从原始对象 s
中获取 A
:
s[["report"]][["A"]]
或
ix <- c("report", "A")
s[[ix]]
假设我有一个嵌套列表,其中包含一堆不同级别的数据框。我想提取仅数据帧的扁平化列表。我如何使用 purrr
函数编写此代码?我应该看看 reduce
吗?
例如,给定数据:
s <- list(x = 1:10,
data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
report = list(A = data.frame(x = 1:3, y = c(2, 4, 6)),
B = data.frame(x = 1:3, y = c(3, 6, 9)),
z = 4:10,
other = data.frame(w = 3:5,
color = c("red", "green", "blue"))))
我想要 return:
的功能list(data = data.frame(report = LETTERS[1:5],
value = rnorm(5, 20, 5)),
`report$A` = data.frame(x = 1:3, y = c(2, 4, 6)),
`report$B` = data.frame(x = 1:3, y = c(3, 6, 9)),
`report$other` = data.frame(w = 3:5,
color = c("red", "green", "blue")))
我写了一个递归函数:
recursive_keep <- function(.x, .f) {
loop <- function(.y) {
if(is.list(.y)) {
c(keep(.y, .f), flatten(map(discard(.y, .f), loop)))
} else if(.f(.y)) {
.y
} else {
NULL
}
}
loop(.x)
}
可以这样称呼:
recursive_keep(s, is.data.frame)
它似乎适用于此示例,但它不保留名称信息。我希望保留足够的信息,以便我可以从原始对象中提取数据。也许这是一个更容易回答的问题?
这个单行函数体的递归函数保留名称并且不使用包:
rec <- function(x, FUN = is.data.frame)
if (FUN(x)) list(x) else if (is.list(x)) do.call("c", lapply(x, rec, FUN))
str(rec(s)) # test
给予(输出后续):
List of 4
$ data :'data.frame': 5 obs. of 2 variables:
..$ report: Factor w/ 5 levels "A","B","C","D",..: 1 2 3 4 5
..$ value : num [1:5] 29.1 19.9 21.2 13 25.2
$ report.A :'data.frame': 3 obs. of 2 variables:
..$ x: int [1:3] 1 2 3
..$ y: num [1:3] 2 4 6
$ report.B :'data.frame': 3 obs. of 2 variables:
..$ x: int [1:3] 1 2 3
..$ y: num [1:3] 3 6 9
$ report.other:'data.frame': 3 obs. of 2 variables:
..$ w : int [1:3] 3 4 5
..$ color: Factor w/ 3 levels "blue","green",..: 3 2 1
关于从 report
中从原始对象 s
中获取 A
:
s[["report"]][["A"]]
或
ix <- c("report", "A")
s[[ix]]