Question

I have a function that sets a vector to a string, copies a Sweave document with a new name and then runs that Sweave. Inside the Sweave document I want to use the vector I set in the function, but it doesn't seem to see it.

(Edit: I changed this function to use tempdir(() as suggested by Dirk)

I created a sweave file test_sweave.rnw;

% 
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}

\title{Test Sweave Document}
\author{gb02413}

\maketitle

<<>>=
ls()
Sys.time()
print(paste("The chosen study was ",chstud,sep=""))
@ 
\end{document}

and I have this function;

onOK <- function(){ 
    chstud<-"test" 
    message(paste("Chosen Study is ",chstud,sep="")) 
    newfile<-paste(chstud,"_report",sep="") 
    mypath<-paste(tempdir(),"\\",sep="")
    setwd(mypath) 
    message(paste("Copying test_sweave.Rnw to ",paste(mypath,newfile,".Rnw",sep=""),sep=""))
    file.copy("c:\\local\\test_sweave.Rnw", 
            paste(mypath,newfile,".Rnw",sep=""), overwrite=TRUE) 
    Sweave(paste(mypath,newfile,".Rnw",sep="")) 
    require(tools) 
    texi2dvi(file = paste(mypath,newfile,".tex",sep=""), pdf = TRUE) 
} 

If I run the code from the function directly, the resulting file has this output for ls();

> ls()
[1] "chstud" "mypath" "newfile" "onOK"

However If I call onOK() I get this output;

> ls()
[1] "onOK"

and the print(...chstud...)) function generates an error.

I suspect this is an environment problem, but I assumed because the call to Sweave occurs within the onOK function, it would be in the same enviroment, and would see all the objects created within the function. How can I get the Sweave process to see the chstud vector ?

Thanks

Paul.

Was it helpful?

Solution 2

OK, I realise that my initial ideas of a 'simple, self contained example' wasn't particularly simple or usefull. So I redid my example and got a sort of answer for myself, although I'd love someone to exaplain why and even suggest a better solution, Here's my example test_sweave.Rnw file

% 
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}

\title{Test Sweave Document}
\author{Paul Hurley}

\maketitle

<<>>=

if(exists("foo")){print(foo)}
ls()
Sys.time()
@ 
\end{document}

If I run this code;

testFoo<-function(){    
  foo<-"My Test String"     
  Sweave("test_sweave.Rnw")     
  require(tools)    
  texi2dvi(file = "test_sweave.tex", pdf = TRUE) 
}

rm(foo) testFoo()

my resulting file does NOT contain the contents of the string foo.

> if (exists("foo")) {
+ print(foo)
+ }
> ls()
[1] "testFoo"

If I run this code (i.e, the same thing, just run directly)

rm(foo)
foo<-"My Test String"
Sweave("test_sweave.Rnw")
require(tools) 
texi2dvi(file = "test_sweave.tex", pdf = TRUE)

my resulting file does contain the foo string

> if (exists("foo")) {
+ print(foo)
+ }
[1] "My Test String"
> ls()
[1] "foo" "testFoo"

and if I run this code

testBar<-function(){
    foo<<-"My Test String"
    Sweave("test_sweave.Rnw")
    require(tools) 
    texi2dvi(file = "test_sweave.tex", pdf = TRUE)
}

rm(foo)
testBar()

My resulting file also contains the foo string

> if (exists("foo")) {
+ print(foo)
+ }
[1] "My Test String"
> ls()
[1] "foo" "testBar" "testFoo"

So, it seems that sweave runs in the global environment, not in the environment it was called from. This means the only way to pass variables to sweave when sweave is run from a function is to use the <<- operator to put the variable in the global environment. (I think).

Anyone else want to comment who knows more about environments ?

OTHER TIPS

I have similar problem. Eventually I found a work-around that "works for me", although it may not be the most elegant way to solve this issue.

Within my function, before 'Sweave' is executed, I put a statement to globally store the local environment:

temp <<- environment()

Using your code example it would look something like:

testFoo<-function(){    
  foo<-"My Test String"
  temp <<- environment()
  Sweave("test_sweave.Rnw")     
  require(tools)    
  texi2dvi(file = "test_sweave.tex", pdf = TRUE) 
}

rm(foo) testFoo()

Then in the LaTeX file to be 'Sweaved' in the beginning of the first chunk I restore the necessary variables, but you can also use 'temp$foo' to access the 'foo' variable that was created within the function. This way I avoid globally storing multiple variables.

% 
\documentclass[a4paper]{article}
\usepackage[OT1]{fontenc}
\usepackage{Sweave}
\begin{document}

\title{Test Sweave Document}
\author{Paul Hurley}

\maketitle

<<>>=

if(exists("foo", envir=temp)) { print(temp$foo) }
ls()
Sys.time()
@ 
\end{document}

Like I wrote above - this works, but is not very elegant.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top