我有一个包含NULL元素的嵌套列表,我想用其他东西替换它们。例如:
l <- list(
NULL,
1,
list(
2,
NULL,
list(
3,
NULL
)
)
)
我想用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")
不幸的是,这两种方法都不起作用,因为rapply
显然忽略了NULL
元素。
如何操作嵌套列表中的NULL
元素?
答案 0 :(得分:8)
我将使用&#34;使用rapply
版本并不会对NULL
&#34;造成奇怪的行为。这是我能想到的最简单的实现:
simple_rapply <- function(x, fn)
{
if(is.list(x))
{
lapply(x, simple_rapply, fn)
} else
{
fn(x)
}
}
(rawr::rapply2
,正如@rawr的评论中所提到的那样是一种更为复杂的尝试。)
现在我可以使用
进行替换simple_rapply(l, function(x) if(is.null(x)) NA else x)
答案 1 :(得分:8)
这就是威廉·邓拉普在2010年提出的这个问题时提出的建议:
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)
答案 2 :(得分:5)
我把替换品包裹在了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)
答案 3 :(得分:4)
这是一个黑客,但就黑客而言,我觉得我对此感到满意。
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
<强>更新强>
如果由于某种原因你需要"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
答案 4 :(得分:1)
这也可以通过rrapply()
软件包中的rrapply
完成。下面是几种不同的方式,可以用NULL
值替换嵌套列表中的NA
元素:
library(rrapply)
l <- list(
NULL,
1,
list(
2,
NULL,
list(
3,
NULL
)
)
)
## replace NULL by NA using only f
rrapply(l, f = function(x) if(is.null(x)) NA else x, how = "replace")
#> [[1]]
#> [1] NA
#>
#> [[2]]
#> [1] 1
#>
#> [[3]]
#> [[3]][[1]]
#> [1] 2
#>
#> [[3]][[2]]
#> [1] NA
#>
#> [[3]][[3]]
#> [[3]][[3]][[1]]
#> [1] 3
#>
#> [[3]][[3]][[2]]
#> [1] NA
## replace NULL by NA using condition argument
rrapply(l, condition = is.null, f = function(x) NA, how = "replace")
#> [[1]]
#> [1] NA
#>
#> [[2]]
#> [1] 1
#>
#> [[3]]
#> [[3]][[1]]
#> [1] 2
#>
#> [[3]][[2]]
#> [1] NA
#>
#> [[3]][[3]]
#> [[3]][[3]][[1]]
#> [1] 3
#>
#> [[3]][[3]][[2]]
#> [1] NA
## replace NULL by NA using condition and deflt arguments
rrapply(l, condition = Negate(is.null), deflt = NA, how = "list")
#> [[1]]
#> [1] NA
#>
#> [[2]]
#> [1] 1
#>
#> [[3]]
#> [[3]][[1]]
#> [1] 2
#>
#> [[3]][[2]]
#> [1] NA
#>
#> [[3]][[3]]
#> [[3]][[3]][[1]]
#> [1] 3
#>
#> [[3]][[3]][[2]]
#> [1] NA
我们还可以通过设置NULL
来修剪列表中的how = "prune"
元素:
## keep only non-NULL elements
rrapply(l, condition = Negate(is.null), how = "prune")
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [[2]][[1]]
#> [1] 2
#>
#> [[2]][[2]]
#> [[2]][[2]][[1]]
#> [1] 3