我正在尝试使用within
和rm
从列表中删除命名组件。这适用于单个组件,但不适用于两个或更多组件。我完全糊涂了。
例如 - 这有效
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
。为什么呢?
答案 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
现在它按预期工作了!