24

我想将当前文件位置作为工作目录。

使用 Rstudio(有效!):

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript writehere.r

# set working directory here
this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")
#This works flawlessly in  MacOS 10.9 and Ubuntu 15.1.

从终端使用命令:Rscript writehere.r(不起作用!)

Error in dirname(parent.frame(2)$ofile) : 
  a character vector argument expected
Execution halted


------------------
(program exited with code: 1)

从终端使用命令:Rscript writehere.r(现在可以使用!)

# Author  : Bhishan Poudel
# Program : writehere.r
# Source  : Rscript example.r

# set working directory here
this_dir <- function(directory)
setwd( file.path(getwd(), directory) )

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

在 ~/.Rprofile 中为 Rstudio 使用函数(有效!):,

##############################################
# inside ~/.Rprofile
# set up working directory
setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
} 
##############################################

然后,在任何目录中,假设我有一个文件 writehere.r,现在它可以工作了。

# Author  : Bhishan Poudel
# Program : writehere.r
# Compile : Rscript writehere.r

# set working directory here
setwd_thisdir

# Sample data to test this code
mydata <- seq(1:10)
write.csv(mydata,"writehere.dat")

问题: 为什么是函数

this.dir <- dirname(parent.frame(2)$ofile) # frame(3) also works.
setwd(this.dir)

不适用于 Rstudio 以外的文本编辑器?

以下是一些有用的链接:
R 将工作目录设置为源文件位置?
用于将工作目录设置为源文件位置的 R 命令在当前工作目录中
获取 `source`d 文件的文件名和路径
setwd()
用于“将工作目录设置为源文件位置”的
命令 SublimeText 和 R:设置当前文件目录
设置工作目录通过函数
永久设置R工作目录的万无一失的方法是什么?
R将工作目录设置为源文件位置?
如何进入R中的文件目录?

4

5 回答 5

5

简单地说,使用 rstudio API,提取其目录,并将其设置为工作目录,如下所示:

setwd(dirname(rstudioapi::getSourceEditorContext()$path))

通过以下命令验证您是否正确设置了目录:

getwd()
于 2019-08-31T11:29:38.127 回答
2

我写了另一个答案,因为你改变了你的问题。有两个有用的事实:

  1. ofilesource函数环境中的变量,因此只有在使用函数运行某些脚本时才能使用它source
  2. 当您从终端运行脚本时,工作目录将设置为终端中的当前目录。

所以,评论你的观察:

  1. 使用 Rstudio(有效!)。是的,如果您按Source(使用该source功能),但如果您按Run(它只是在 R 控制台中运行命令),则不是。
  2. Rscript writehere.r(不起作用!)。那是因为您正在寻找而ofile无需调用source.
  3. Rscript writehere.r(现在工作!)。是的,但它只是根据事实 2起作用:代码this_dir <- function(directory) setwd( file.path(getwd(), directory) )是不必要的,因为它只是一个名为this_dir.
  4. Rstudio(工作!)。第一部分:好的。第二部分。它只是按事实 2工作。特别setwd_thisdir是没有必要,因为它只是将主体打印setwd_thisdir到控制台。

总而言之,当您使用函数获取脚本但无法访问函数选项时setwd(dirname(parent.frame(2)$ofile)),这是一个有用的技巧:例如,当您在 R-Studio 中按Source时。在可能的情况下使用 intead函数。如果您从终端运行脚本,只需将终端设置为脚本文件夹。sourcesourcesourcechdir=TRUE

于 2018-03-20T11:54:12.233 回答
1

尝试parent.frame(3)在你的功能中使用:

setwd_thisdir <- function () {
  this.dir <- dirname(parent.frame(3)$ofile)
  setwd(this.dir)
}

请参阅?parent.framehttp://adv-r.had.co.nz/Environments.html#calling-environments

您还可以查看函数 ( )的chdir选项。source?source

于 2016-03-27T23:43:34.313 回答
1

我给出的第一个答案完全没有抓住重点,因为我没有仔细研究你想要实现的目标。然而,这里提出的解决方案应该可以解决问题。

首先注意在帮助文件中source有一个参数chdir描述为:logical; 如果TRUE并且file是路径名,则 R 工作目录临时更改为包含file用于评估的目录。

每次要获取文件时手动指定该参数会很麻烦,因此让我们向 .Rprofile 添加一些内容,以更改chdirfrom FALSEto的默认值TRUE

-functionformals可用于修改默认值,但当用于属于其他环境的函数时,结果将是创建该函数的本地副本。这还不够好。

可能有几种方法可以解决这个问题,但是source当我将它插入 .Rprofile 时,下面的小技巧对我有用。

.temporary_copy_source <- base::source
formals(.temporary_copy_source)$chdir <- TRUE
utils::assignInNamespace(
    x = "source",
    value = .temporary_copy_source,
    ns = environment(source))
rm(.temporary_copy_source)

一个警告:这里介绍的方法原则上允许用户修改任何函数中任何参数的默认值,但这样做是一个非常糟糕的主意。请记住,您的脚本以后可能会与不具有与您相同的 .Rprofile 的人共享。 永远不要编写需要对命名空间进行此类修改的代码!

于 2016-04-09T11:27:39.087 回答
1

更新:我意识到这个答案根本没有帮助,我会发布另一个可以解决问题的答案。

只要您要运行的代码不需要任何额外的参数,如下图所示的解决方案,使用eval(expr, envir)可能就可以解决问题。

考虑以下使用 的示例,在命令行上使用时print(environment())应该返回。environment: R_GlobalEnv该函数test_1将打印有关调用该函数时创建的内部环境的信息,而该函数test_2将返回所需的结果。

test_1 <- function(){
     print(environment())
}

test_2 <- function(){
    .expr <- quote({
        print(environment())
        })
    .envir <- sys.frame(which = -1)
    eval(expr = .expr,
         envir = .envir)
}

sys.frame(which = -1)确保在调用函数的环境中计算表达式。如果你确定你总是想使用全局环境,那么最好使用.GlobalEnv. 引用您要使用的表达式也很重要,否则它可能无法按预期工作。

此解决方案的一个不错的功能是您无需调整要放入​​函数的代码,只需引用它即可。

最后:可以扩展这种方法,以便您的函数可以接受参数,然后将这些参数提供给您要在另一个环境中评估的代码。但是,这将需要对您要评估的表达式进行一些重要的调整;您可能需要使用bquote+.()构造 - 您可能还需要使用calland do.call

于 2016-04-09T08:11:39.810 回答