如何以相对方式使用setwd?

时间:2019-06-17 10:06:52

标签: r git

我们的团队在git repos中使用R脚本,这些脚本在Mac和Windows(有时是Linux)计算机上由多个人共享。这往往会导致在脚本顶部出现一堆非常烦人的行,如下所示:

#path <- 'C:/data-work/project-a/data'
#path <- 'D:/my-stuff/project-a/data'
path = "~/projects/project-a/data"
#path = 'N:/work-projects/project-a/data'
#path <- "/work/project-a/data"
setwd(path)

要运行脚本,我们必须注释/取消注释正确的路径变量,否则脚本将无法运行。这很烦人,不整洁,而且在提交历史记录中也很混乱。

过去,通过使用shell脚本来设置相对于脚本位置的目录并完全跳过setwd(然后使用./run-scripts.sh而非Rscript process.R),可以避免这种情况,但是Windows用户在这里,那是行不通的。是否有更好的方法来简化R中这些凌乱的setwd()样板?

(旁注:在Python中,我通过使用路径库来获取脚本文件本身的位置,然后从中建立相对路径来解决此问题。但是R似乎没有办法获取位置正在运行的脚本文件的内容?)

3 个答案:

答案 0 :(得分:5)

答案是永远不要使用setwd()。当然,R的功能与Python有所不同,但这是它们的共同点。

相反,您正在执行的任何脚本都应假定它们是从公共的顶级根文件夹运行的。启动新的R进程时,其工作目录(即getwd()所提供的目录)被设置为与产生该进程的目录相同的文件夹。

例如,如果您使用以下布局:

.
├── data
│   └── mydata.csv
└── scripts
    └── analysis.R

您将从analysis.R运行.,而analysis.Rdata/mydata.csv引用为“ data / mydata.csv”(例如read.csv("data/mydata.csv, stringsAsFactors = FALSE))。 我会保留运行R脚本的Shell脚本或Makefile,并让R脚本假定它们是从git存储库的顶层运行的。

这看起来像:

cd . # Whereever `.` above is
Rscript scripts/analysis.R

进一步阅读:

答案 1 :(得分:1)

  

在Python中,我通过使用路径库来获取脚本文件本身的位置,然后从中建立相对路径来解决此问题。但是R似乎没有办法获取正在运行的脚本文件的位置?

不幸的是,

R本身没有办法。但是您可以通过以下两种方法之一来获得相同的结果:

  • 在通过source包含代码的情况下,请使用软件包而不是脚本。然后,您可以使用变形虫的答案中概述的解决方案。之所以可行,是因为真正的问题是R无法告诉source函数在哪里寻找脚本。
  • 使用klmr/modules代替source。该软件包提供了一个模块系统,允许相对导入代码模块。这样做的一个很好的副作用是,该包提供了一个函数,该函数可以告诉您当前脚本的路径,就像在Python中一样(而且,就像在Python中一样,通常不需要直接使用此函数)。 / li>

答案 2 :(得分:1)

1)如果您正在寻找一种方法来查找当前正在运行的脚本的路径,请参见:

electron-rebuild

2)另一种方法是要求用户在其.Rprofile文件中放置一个具有预定名称的选项。然后脚本可以setwd来执行此操作。该系统的一个吸引人的方面是,随着时间的流逝,人们可能会忘记各种项目的位置,而使用此系统,人们只能看着.Rprofile文件来提醒自己。例如,对于projectA,每个运行该项目的人都会将其放入他们的.Rprofile

options(projectA = "...whatever...")

,然后脚本将从以下位置开始:

proj <- getOption("projectA")
if (!is.null(proj)) setwd(proj) else stop("Set option 'projectA' to its directory")

如果未定义projectA,则此方法的一种变化是采用当前目录。尽管这似乎更灵活,但我个人认为上述代码的文档功能是一个很大的优势。

proj <- getOption("projectA")
if (!is.null(proj)) setwd(proj) else cat("Using", getwd(), "\n")