2015-11-25 6 views
5

withinrmを使用して、リストから名前付きコンポーネントを削除しようとしています。これは、単一のコンポーネントでは機能しますが、複数のコンポーネントでは機能しません。私は完全に混乱している。例えばwithin()内の複数の名前付きリストコンポーネントを削除する

- これはwithinからの出力は、単に非取り外したコンポーネントを持つことになります

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

に動作します。

しかし、このされていません。

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

どちらこれを行います。withinから

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

出力はNULLに設定私は削除しようとしているもので、すべてのコンポーネントを、持っています。どうして?

+0

'aa ['a'] < - NULL'? – etienne

+0

さて、はい。しかし、私は内部でそれをやろうとしています – martin

+0

これは奇妙な行動です! 1つを削除することはできますが、それ以降は3つ以上の列があってもNULLのままです。 'within(aa、{" b "< - NULL;" a "< - NULL})と同様に動作します。 – jeremycg

答えて

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ためのコードを見てみましょう:関数の最後の行に2番目で、特に

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より大きい場合、vector("list", 2)は各アイテムがNULLである2つのアイテムリストを作成するので、関数は本質的にaa[c('a', 'b')] <- list(NULL, NULL)を呼び出しています。

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 

は、今では動作します私たちは、関数の最後の行に2番目からelseステートメントを削除withinの私たち自身のバージョンを作成することができます!

+0

ああ、そうです。ソースを見ることを考えていたはずです。非常に感謝します! – martin

+0

これはとても素敵ですが、なぜあなたは 'within.list'からelse節を削除する必要がありますか?それがバグだと仮定して、 'base :: within'にRバグを書いてください – smci

関連する問題