代码之家  ›  专栏  ›  技术社区  ›  PaulHurleyuk

如果从函数运行,swave无法看到向量?

  •  1
  • PaulHurleyuk  · 技术社区  · 16 年前

    我有一个函数,它将向量设置为一个字符串,用一个新名称复制一个swave文档,然后运行该swave。在swave文档中,我想使用我在函数中设置的向量,但它似乎看不到。

    (编辑:我将此函数更改为使用tempdir((),由dirk建议)

    我创建了一个swave文件测试_swave.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…)函数会生成一个错误。

    我怀疑这是一个环境问题,但我假设是因为调用swave发生在onok函数中,它将处于相同的环境中,并且将看到在该函数中创建的所有对象。怎样才能让swave过程看到chstud向量?

    谢谢

    保罗。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Michal J Figurski    15 年前

    我也有类似的问题。最终,我找到了一份“适合我”的工作,尽管这可能不是解决这个问题最优雅的方法。

    在我的函数中,在执行“swave”之前,我放置了一个语句来全局存储本地环境:

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

    然后,在第一个块开始处要“swaved”的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}
    

    就像我上面写的-这是作品,但不是很优雅。

        2
  •  0
  •   PaulHurleyuk    16 年前

    好吧,我意识到我最初的想法“简单,自我包含的例子”并不是特别简单或有用。所以我重新举出了我的例子,并为自己找到了一个答案,尽管我希望有人能解释为什么,甚至提出一个更好的解决方案, 这是我的示例测试文件

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

    因此,似乎swave是在全球环境中运行的,而不是在它所调用的环境中。这意味着当swave从函数运行时,将变量传递给swave的唯一方法是使用<<-运算符将变量放入全局环境中。(我想)。

    还有谁想评论谁更了解环境?