如何操作嵌套列表中的NULL元素?

时间:2016-08-15 06:00:48

标签: r list

我有一个包含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元素?

5 个答案:

答案 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