Sweave не видит вектор при запуске из функции?

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

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

Я создал файл свейва 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?

Спасибо

Павел.


person PaulHurleyuk    schedule 26.05.2010    source источник
comment
Не могли бы вы смоделировать полный автономный пример, желательно в портативном виде (например, с использованием tempdir() или tempfile())?   -  person Dirk Eddelbuettel    schedule 26.05.2010
comment
Я попытался переписать функцию. Дайте мне знать, если я полностью упустил смысл использования tempdir()/tempfile().   -  person PaulHurleyuk    schedule 26.05.2010
comment
Я все еще не понимаю вашего вопроса. Какова, по вашему мнению, связь между фрагментом кода и файлом Sweave? Я не вижу никого, но, возможно, мне не хватает кофе.   -  person Dirk Eddelbuettel    schedule 26.05.2010
comment
Ах, верно, в моем примере выше этого нет, в моей исходной проблеме я хотел использовать вектор chstud, чтобы что-то делать, я обновлю его снова....   -  person PaulHurleyuk    schedule 26.05.2010
comment
На самом деле я задал этот вопрос в справочном списке R, и Дункан Мердок дал отличный ответ, который действительно помог. См. mail-archive.com/r-help@r -project.org/msg97762.html   -  person PaulHurleyuk    schedule 31.05.2010


Ответы (2)


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

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

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

person Michal J Figurski    schedule 24.01.2011

Хорошо, я понимаю, что мои первоначальные идеи о «простом, автономном примере» не были особенно простыми или полезными. Итак, я переделал свой пример и получил своего рода ответ для себя, хотя мне бы хотелось, чтобы кто-нибудь объяснил, почему, и даже предложил лучшее решение. Вот мой пример файла test_sweave.Rnw

% 
\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 работает в глобальной среде, а не в той среде, из которой он был вызван. Это означает, что единственный способ передать переменные для sweave, когда sweave запускается из функции, — это использовать оператор ‹‹- для помещения переменной в глобальное окружение. (Я думаю).

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

person PaulHurleyuk    schedule 28.05.2010