Как управлять элементами NULL во вложенном списке?
У меня есть вложенный список, содержащий элементы NULL, и я хотел бы заменить их чем-то другим. Например:
l <- list(
NULL,
1,
list(
2,
NULL,
list(
3,
NULL
)
)
)
Я хочу заменить NULL-элементы на NA. Естественным способом сделать это является рекурсивный цикл над списком с помощью 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
во вложенном списке?
Ответы
Ответ 1
Я собираюсь использовать "использование версии rapply
, не имеет странного поведения с NULL
". Это самая простая реализация, о которой я могу думать:
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)
Ответ 2
Это то, что предложил Уильям Данлэп в 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)
Ответ 3
Это взломать, но, насколько я понимаю, я немного доволен этим.
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
Update:
Если по какой-то причине вам понадобилось "NULL"
в качестве символьной записи в списке (например, в углу), вы все равно можете использовать вышеупомянутый взлом, поскольку он заменяет содержимое строки, а не кавычки, поэтому она просто требует еще один шаг
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
Я завернул замену внутри 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)