如何以相对路径方式使用setwd?

5

我们的团队使用R脚本在git存储库中,这些存储库在多个人之间共享,并跨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中,我通过使用path库获取脚本文件本身的位置,然后从中构建相对路径来解决此问题。但是,R似乎没有办法获取正在运行的脚本文件的位置?)
3个回答

7
答案就是永远不要使用setwd()。R和Python的处理方式肯定有所不同,但这是它们共同之处之一。
相反,任何你要执行的脚本都应该假设它们是从一个公共的、顶层的、根目录下运行的。当你启动一个新的R进程时,它的工作目录(即getwd()给出的目录)被设置为与进程所在的文件夹相同。
例如,如果你有这样的布局:
.
├── data
│   └── mydata.csv
└── scripts
    └── analysis.R

您需要从当前目录运行analysis.R,而analysis.R会将data/mydata.csv作为"data/mydata.csv"引用(例如:read.csv("data/mydata.csv, stringsAsFactors = FALSE))。我建议您保留脚本或Makefile来运行R脚本,并使R脚本假定它们是从git仓库的顶层运行的。可能看起来像这样:
cd . # Whereever `.` above is
Rscript scripts/analysis.R

更多阅读:


2
here 真是太棒了。使用您的目录,您可以在根目录中拥有一个项目或 .here 文件。然后,要获取脚本的目录,您只需执行 here('scripts', 'analysis.R') 即可完成。 - Cole
2
哦,我喜欢here库。我要使用它。 - futuraprime

1

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

Rscript: 确定正在执行的脚本的路径

2) 另一种方法是要求用户在其.Rprofile文件中放置预先安排的名称选项。然后,脚本可以setwd到该文件夹。这个系统的一个有吸引力的方面是,随着时间的推移,人们可能会忘记各种项目的位置,而有了这个系统,人们只需查看.Rprofile文件就可以提醒自己。例如,对于项目A,每个运行该项目的人都会将此内容放入其 .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")

1
在Python中,我使用路径库来获取脚本文件本身的位置,然后从那里构建相对路径来解决这个问题。但是R似乎没有办法获取正在运行的脚本文件的位置?很遗憾,R本身没有这样的方法。但你可以通过以下两种方式实现同样的结果:使用包而不是脚本,其中你通过source包含代码。然后你可以使用amoeba答案中概述的解决方案。这起作用的原因是R无法告诉source函数在哪里查找脚本。或者使用box::use而不是source。'box'包提供了一个模块系统,允许相对导入代码模块。这样做的一个好处是,该包提供了一个函数,告诉你当前脚本的路径,就像在Python中一样(并且,就像在Python中一样,你通常不需要直接使用此函数)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接