From maechler at stat.math.ethz.ch  Thu Feb 26 10:35:23 2004
From: maechler at stat.math.ethz.ch (Martin Maechler)
Date: Thu Feb 26 10:35:28 2004
Subject: [Rd] Re: Constructing an environment from a data.frame
In-Reply-To: <402A04D4.6000501@statistik.uni-dortmund.de>
References: <97di201lmt4olugcajuejn1jmi8ifm8cc0@4ax.com>
	<402A04D4.6000501@statistik.uni-dortmund.de>
Message-ID: <16445.48603.889996.284100@gargle.gargle.HOWL>

[Diverted to R-devel]

>>>>> "UweL" == Uwe Ligges <ligges@statistik.uni-dortmund.de>
>>>>>     on Wed, 11 Feb 2004 11:32:52 +0100 writes:

    UweL> Duncan Murdoch wrote:
    >> Code like
    >> 
    >> df <- data.frame(x=1:10)
    >> y <- 20:29
    >> 
    >> eval(quote(x+y), env=df)
    >> 
    >> does what you might expect:  it looks for x and y in the data.frame,
    >> and when it doesn't find y there, it looks in the parent environment.
    >> 
    >> However, sometimes I'd like to construct a single environment out of
    >> df, so that I can pass it to nested functions and get the same
    >> behaviour.  Right now, I get the wrong answer from code like this:
    >> 
    >> f1 <- function(df) {
    >> g <- function() {
    >> eval(quote(x+y), env=df)
    >> }
    >> y <- 1:10
    >> g()
    >> }
    >> 
    >> f1(df)
    >> 
    >> because the eval looks in the environment of f1, finds y there, and
    >> gives me the wrong answer.
    >> 
    >> I can modify f1 so it works:
    >> 
    >> f2 <- function(df) {
    >> g <- function(env) {
    >> eval(quote(x+y), env=df, enclos=env)
    >> }
    >> y <- 1:10
    >> g(parent.frame())
    >> }
    >> 
    >> but this means carrying around both parent.frame() and df.  I'd like
    >> to do this:
    >> 
    >> f3 <- function(df) {
    >> env <- as.environment(df)
    >> 
    >> g <- function() {
    >> eval(quote(x+y), env=env)
    >> }
    >> 
    >> y <- 1:10
    >> g()
    >> }
    >> 
    >> and get the same result as from f2(df), but currently as.environment
    >> doesn't like to be passed a data.frame.  Is there a better way to do
    >> the same thing?
    >> 
    >> Duncan Murdoch

    UweL> I don't think it's easily possibe (but Luke et al. might want to correct 
    UweL> me). My dirty solution would be:

    UweL> f4 <- function(df) {
    UweL>   env <- new.env()
    UweL>   mapply(function(x, y) assign(y, x, envir=env), df, names(df))
    UweL>   g <- function()
    UweL>      eval(quote(x+y), env=env)
    UweL>   y <- 1:10
    UweL>   g()
    UweL> }
    UweL> f4(df)

I do think the best would be to extend  as.environment() 
to make it work with data.frame and as a matter of fact any
list.

Uwe's code above

   env <- new.env()
   mapply(function(x, y) assign(y, x, envir=env), df, names(df))

would suggest a simplistic  R level implementation of as.environment.list().
But then, as.environment() is primitive,
and as John Chambers is the author of as.environment() and as he has
been travelling recently, I'm addressing this explicitely for further
comments.

Martin


[Rd] Re: Constructing an environment from a data.frame
Martin Maechler