[R] conditional assignments and calculations
Gabor Grothendieck
ggrothendieck at myway.com
Sun Oct 3 08:05:16 CEST 2004
Michael Lachmann <lachmann <at> eva.mpg.de> writes:
:
: Hello!
:
: I am using the TeXmacs interface to R. (Though I encountered a similar
: problem when using Sweave)
: In doing calculations I often ecounter this scenario: I'll have some
: calculations in my file:
: --
: A=read.lots.of.data()
:
: B=huge.calculation.on(A)
:
: C=another.calculation.on(B)
: --
: Now, if A has already been read, I don't need to re-read it. If B has
: already been calculated, I don't need to recalculate it. But I would
: like to be able to just press 'enter' on each of them.
:
: So, I would like R to somehow figure out dependencies (a bit like in
: Makefiles)
:
: I implemented something like this with the following functions:
: ----------------------
: touch=function(x) {attr(x,"last.updated")=Sys.time();x}
:
: last.updated=function(a) {
: if( length(attr(a,"last.updated")) == 0 ) {
: Sys.time()
: } else {
: attr(a,"last.updated")
: }
: }
:
: "depends<-"=function(a,value,...) {
: args=list(...)
: if( length(attr(a,"last.updated")) == 0 ) {
: a <- value
: a <-touch(a)
: } else {
: lu=(sapply(args,function(x) last.updated(x)-last.updated(a) > 0 ))
: if( sum(lu)>0 ) {
: a <- value
: a <-touch(a)
: }
: }
: a
: }
: ------------------------
: Then I can implement what I wanted above as follows:
: --
: if( !exists(A) ) { A=read.lots.of.data(); A=touch(A) }
:
: depends(B,A)=huge.calculation.on(A)
: # this means the assignment 'B=huge.calculation.on(A)' is
: # done only if A has been updated more recently than B.
:
: depends(C,B)=another.calculation.on(B)
: # dito for C more recent than B.
: --
: And now I can carelessly press 'enter' on these expression that might
: otherwise take hours to compute. Each variable has a datestamp of the
: last time it was updated, and I do each calculation conditional on
: whether certain variables have been recently changed. I can also save
: A,B,C to a file,later load them, and the calculations will not be redone.
:
: But this solution is quite ugly, because of several problems:
:
: 1. To call 'depends(A,B)=f(B)' the first time, A has to already exist,
: otherwise I get an error (before I enter the "depends<-" function.)
The technique used to implement mulitple return values shown in
http://tolstoy.newcastle.edu.au/R/help/04/06/1406.html
could be adapted to this problem. Using that technique the code would
look like this:
depends[A,B] <- f(B)
and A would not have to pre-exist.
You define a structure with a class of depends, say:
depends <- structure(NA, class = "depends")
and then define the [<-.depends action on that structure
in an analogous way to what was done there.
: 2. I would also like to have a convenient way to do
: "if( !exists(A) ) { A=read.lots.of.data(); A=touch(A) }"
: maybe something like:
: depends(A)<-read.lots.of.data()
: But that doesn't work, because of 1.
: or
: A %set% read.lots.data()
: But that doesn't work, because I haven't figured out a way for a
: function to change one of its variables.
: (Maybe I could do A=A %set read.lots.of.data(), but that is really ugly...)
Is this what you want?
R> f <- function(x,v) assign(as.character(substitute(x)), v, parent.frame())
R> x # x does not exist
Error: Object "x" not found
R> f(x,3)
R> x # now it does
[1] 3
<<- can be used if the eval.parent is a third way (see #3 below).
: 3. It would be nice to be able to do touch(A) instead of A=touch(A)
touch <- function(x)
eval.parent(substitute(attr(x,"last.updated")<-Sys.time()))
x <- 3
touch(x)
:
: 4. If I modify A without calling 'A=touch(A)', then B will not be
: updated next time I call 'depends(B,A)=huge.calculation.on(A)'. So it
: would be nice to have the variable's 'last updated' time updated
: automatically. (Though then it is a bit problematic to decide what the
: 'last updated' time should be for variables loaded from a file...)
If its done in a function you could use on.exit to ensure that it gets
updated when leaving the function.
:
: 5. The whole thing is rather cludgy. But I haven't found a good way to
: implement it.
:
: Suggestions?
:
: Thanks,
:
: Michael
:
More information about the R-help
mailing list