在within()中删除多个命名列表组件

时间:2015-11-25 17:53:06

标签: r list null with-statement named

我正在尝试使用withinrm从列表中删除命名组件。这适用于单个组件,但不适用于两个或更多组件。我完全糊涂了。

例如 - 这有效

aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a)})

within的输出只包含未删除的组件。

然而,这不是:

aa = list(a = 1:3, b = 2:5, cc = 1:5)
within(aa, {rm(a); rm(b)})

这两个都没有:

within(aa, {rm(a, b)})

within的输出将包含我尝试删除的所有组件,设置为NULL。为什么呢?

1 个答案:

答案 0 :(得分:4)

首先,请注意以下行为:

> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> aa[c('a', 'b')] <- NULL
>
> aa
# $cc
# [1] 1 2 3 4 5

> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> aa[c('a', 'b')] <- list(NULL, NULL)
>
> aa
# $a
# NULL
#
# $b
# NULL
#
# $cc
# [1] 1 2 3 4 5

现在让我们看一下within.list的代码:

within.list <- function (data, expr, ...) 
{
    parent <- parent.frame()
    e <- evalq(environment(), data, parent)
    eval(substitute(expr), e)
    l <- as.list(e)
    l <- l[!sapply(l, is.null)]
    nD <- length(del <- setdiff(names(data), (nl <- names(l))))
    data[nl] <- l
    if (nD) 
        data[del] <- if (nD == 1) NULL else vector("list", nD)
    data
}

特别注意函数的倒数第二行。如果列表中已删除项目的数量大于1,则该函数实际上是调用aa[c('a', 'b')] <- list(NULL, NULL),因为vector("list", 2)创建了两个项目列表,其中每个项目为NULL。我们可以创建自己的within版本,我们从函数的倒数第二行删除else语句:

mywithin <- function (data, expr, ...) 
{
    parent <- parent.frame()
    e <- evalq(environment(), data, parent)
    eval(substitute(expr), e)
    l <- as.list(e)
    l <- l[!sapply(l, is.null)]
    nD <- length(del <- setdiff(names(data), (nl <- names(l))))
    data[nl] <- l
    if (nD) data[del] <- NULL
    data
}

现在让我们测试一下:

> aa = list(a = 1:3, b = 2:5, cc = 1:5)
>
> mywithin(aa, rm(a, b))
# $cc
# [1] 1 2 3 4 5

现在它按预期工作了!