Sweave не видит вектор, если запускается из функции - PullRequest
1 голос
/ 26 мая 2010

У меня есть функция, которая устанавливает вектор в строку, копирует документ Sweave с новым именем и затем запускает этот Sweave. Внутри документа Sweave я хочу использовать вектор, который я установил в функции, но он, похоже, его не видит.

(Edit: я изменил эту функцию, чтобы использовать tempdir ((), как предложено Dirk)

Я создал Sweave-файл 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}

и у меня есть эта функция;

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

Если я запускаю код из функции напрямую, полученный файл будет иметь такой вывод для ls ();

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

Однако, если я вызываю onOK (), я получаю этот вывод;

> ls()
[1] "onOK"

и функция print (... chstud ...)) выдает ошибку.

Я подозреваю, что это проблема среды, но я предположил, что вызов Sweave происходит внутри функции onOK, он будет в той же среде и будет видеть все объекты, созданные внутри функции. Как я могу заставить процесс Sweave увидеть вектор chstud?

Спасибо

Paul.

Ответы [ 2 ]

2 голосов
/ 24 января 2011

У меня похожая проблема. В конце концов я нашел обходной путь, который «работает для меня», хотя, возможно, это не самый элегантный способ решения этой проблемы.

В моей функции перед выполнением Sweave я поместил оператор для глобального хранения локальной среды:

temp <<- environment()

Используя ваш пример кода, это будет выглядеть примерно так:

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

rm(foo) testFoo()

Затем в файле LaTeX, который будет «Sweaved» в начале первого блока, я восстанавливаю необходимые переменные, но вы также можете использовать «temp $ foo» для доступа к переменной «foo», которая была создана внутри функции. Таким образом, я избегаю глобального хранения нескольких переменных.

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

Как я уже писал выше - это работает, но не очень элегантно.

0 голосов
/ 28 мая 2010

Хорошо, я понимаю, что мои первоначальные идеи «простого, самодостаточного примера» не были особенно простыми или бесполезными. Поэтому я переделал свой пример и получил своего рода ответ для себя, хотя я хотел бы, чтобы кто-то объяснил, почему и даже предложил лучшее решение, Вот мой пример 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}

Если я запускаю этот код;

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

rm(foo) testFoo()

мой полученный файл НЕ содержит содержимого строки foo.

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

Если я запускаю этот код (т. Е. То же самое, просто запускаю напрямую)

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

мой полученный файл содержит строку foo

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

и если я запускаю этот код

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

rm(foo)
testBar()

Мой полученный файл также содержит строку foo

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

Итак, похоже, что Sweave работает в глобальной среде, а не в той среде, из которой он был вызван. Это означает, что единственный способ передать переменные в свипирование при запуске свипирования из функции - это использовать оператор << - для помещения переменной в глобальную среду. (Думаю). </p>

Кто-нибудь еще хочет прокомментировать, кто знает больше об окружающей среде?

...