Удаление нескольких именованных компонентов списка в пределах ()

Я пытаюсь удалить именованный компонент из списка, используя 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, Зачем?

1 ответ

Во-первых, обратите внимание на следующее поведение:

> 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
}

В частности, посмотрите на последнюю строку функции. Если количество удаленных элементов в списке больше единицы, функция по сути вызывает 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

Теперь все работает как положено!

Другие вопросы по тегам