我有一个包含NULL元素的嵌套列表,我想用其他东西替换它们.例如:
l <- list(
NULL,
1,
list(
2,
NULL,
list(
3,
NULL
)
)
)
Run Code Online (Sandbox Code Playgroud)
我想用NA替换NULL元素.这样做的自然方法是使用递归循环遍历列表rapply
.我试过了:
rapply(l, function(x) NA, classes = "NULL", how = "replace")
rapply(l, function(x) if(is.null(x)) NA else x, how = "replace")
Run Code Online (Sandbox Code Playgroud)
不幸的是,这些方法都不起作用,因为rapply
显然忽略了NULL
元素.
如何操作NULL
嵌套列表中的元素?
我要去"使用一个rapply
不具有奇怪行为的版本NULL
".这是我能想到的最简单的实现:
simple_rapply <- function(x, fn)
{
if(is.list(x))
{
lapply(x, simple_rapply, fn)
} else
{
fn(x)
}
}
Run Code Online (Sandbox Code Playgroud)
(rawr::rapply2
正如@rawr的评论中提到的那样是一种更复杂的尝试.)
现在我可以使用替换
simple_rapply(l, function(x) if(is.null(x)) NA else x)
Run Code Online (Sandbox Code Playgroud)
这就是William Dunlap在2010年提出的问题时提出的问题:Rhelp:
replaceInList <- function (x, FUN, ...)
{
if (is.list(x)) {
for (i in seq_along(x)) {
x[i] <- list(replaceInList(x[[i]], FUN, ...))
}
x
}
else FUN(x, ...)
}
replaceInList(l, function(x)if(is.null(x))NA else x)
Run Code Online (Sandbox Code Playgroud)
这是一个 hack,但就 hack 而言,我想我对它有些满意。
lna <- eval(parse(text = gsub("NULL", "NA", deparse(l))))
str(lna)
#> List of 3
#> $ : logi NA
#> $ : num 1
#> $ :List of 3
#> ..$ : num 2
#> ..$ : logi NA
#> ..$ :List of 2
#> .. ..$ : num 3
#> .. ..$ : logi NA
Run Code Online (Sandbox Code Playgroud)
更新:
如果由于某种原因您需要"NULL"
作为列表中的字符条目(角情况,很多?)您仍然可以使用上面的 hack 因为它替换了字符串的内容,而不是引号,因此它只需要另一个步骤
l2 <- list(
NULL,
1,
list(
2,
"NULL",
list(
3,
NULL
)
)
)
lna2 <- eval(parse(text = gsub("NULL", "NA", deparse(l2))))
lna2_2 <- eval(parse(text = gsub('\\"NA\\"', '\"NULL\"', deparse(lna2))))
str(lna2_2)
#> List of 3
#> $ : logi NA
#> $ : num 1
#> $ :List of 3
#> ..$ : num 2
#> ..$ : chr "NULL"
#> ..$ :List of 2
#> .. ..$ : num 3
#> .. ..$ : logi NA
Run Code Online (Sandbox Code Playgroud)
我将替换包包裹在sapply内,这使它对我更具可读性/可理解性,尽管通用性较低。
replace_null <- function(x) {
lapply(x, function(x) {
if (is.list(x)){
replace_null(x)
} else{
if(is.null(x)) NA else(x)
}
})
}
replace_null(l)
Run Code Online (Sandbox Code Playgroud)