我听说它说在脚本中使用setwd()
是不好的做法。
答案 0 :(得分:28)
这是一个可重现代码的问题。如果您指定其他人的计算机上不存在的目录,则他们无法使用您的代码。对于绝对文件路径,这尤其糟糕,特别是对于Windows文件路径(在Unix系统上绝对无法复制),这一点很糟糕。
我首选的解决方案是在开始运行代码之前指定用户应该位于自己系统上的相关目录中。如果为了您自己的方便,您希望在代码顶部放置setwd(...)
权限,其他人可以注意到并在适当时将其注释掉,但其余代码只假定该起始目录中的相对路径,这对我没关系。
knitr
的作者)对此特别强烈:
https://groups.google.com/forum/?fromgroups=#!topic/knitr/knM0VWoexT0
每当你想操纵文件时,它们都被假定为 源的同一目录(例如Rnw文档)。然后你可以 总是使用相对路径,你永远不需要setwd()。运用 setwd()与可重复性原理相矛盾,例如:您 使用setwd('foo / bar /'),其他目录可能不存在 人的电脑。见常见问题7: https://github.com/yihui/knitr/blob/master/FAQ.md
从前面提到的FAQ 7:
你最好不要这样做[更改knitr代码中的工作目录 块。您的工作目录始终是getwd()(所有输出文件 将写在这里),但代码块在下面进行评估 输入文档来自的目录。改变工作 运行R代码时的目录通常是一种不好的做法。见#38 讨论。您还应该尝试避免使用绝对目录 尽可能(使用相对目录),因为它 事情再现性较差。
答案 1 :(得分:6)
我无法想到在我管理的服务器上运行脚本时使用setwd()
的任何特定问题,因为它确实返回了可以使用try()捕获的错误,并且您可以对其进行管理。我对路径懒惰时使用了setwd()
- 见下文!
我在脚本制作或其他方面广泛使用file.path()
。处理输入目录中的文件并将输出图形和报告放在其他位置。所以有些东西......(未经测试)使用setwd()
这会有点乏味。
kInDir <- '~/Indir'
kOutDir <- '~/Outdir'
flist <- dir(path=kInDir, pattern='^[a-z]{2,5}\\.csv$')
# note I could have used full.names=T - but it's easier not to...
for (fnam in flist) {
# full path to the report file created
sfnam <- file.path(kOutDir, gsub('.csv', '_report.txt', fnam))
# full path to the csv file that will be created
ofnam <- file.path(kOutDir, gsub('.csv', '_b.csv', fnam))
#
# ok... we're going to process this CSV file...
r1 <- read.csv(file.path(kInDir, fnam))
#
# we''ll put the output from the analysis into this report file
sink(sfnam, split=TRUE)
# processs it... into a new data.frame k1
# blah blah blah...
#
write.csv(k1, file=ofnam, row.names=FALSE)
sink() # turn off this particular report file
}
答案 2 :(得分:5)
寻找更好的替代问题:
我主要将R用于个别项目(这意味着我是主要的分析师)。但是,我们确实在有时需要与他人共享的项目中使用这些。
我发现 RStudio 项目功能为 long way 以保持文件整理有序。如果其他用户也采用RStudio,他们会很高兴能够打开一个文件(“* .Rproj”)并让项目加载到您上次保存的状态。
除此之外,我还找到了一个新工具 ProjectTemplate 更进了一步!作者开发的技术用于为您正在做的事情提供结构。请访问网站了解更多详情。
答案 3 :(得分:4)
虽然针对setwd()的问题已经定位,但我想在问题的替代部分添加一个问题。我们经常使用相对路径非常方便的git
setrelwd <- function(rel_path){
curr_dir <- getwd()
abs_path <- file.path(curr_dir,rel_path)
if(dir.exists(abs_path)){
setwd(abs_path)
}
else
{
warning('Directory does not exist. Please create it first.')
}
}
> setrelwd("Summer2016")
Warning message:
In setrelwd("Summer2016") : Directory does not exist. Please create it first.
此外,如果您不想看到警告消息但是立即创建文件夹,请参阅Check existence of directory and create if doesn't exist
答案 4 :(得分:3)
为了让我在工作中更轻松,我们都把它放在Rprofile
中hdrive=
switch(Sys.info()[[1]],
'Linux'="/mnt/hdrive",
'Windows'="H:/",
"Darwin"="/Volumes/hdrive/mnt/hdrive"
)
所以我总是有这个变量让我进入我们的共享驱动器。然后在我的脚本中我们可以写
setwd(paste(hdrive,"/relative/path/",sep="/"))
这样可以解决其他人正在谈论的一些问题。
答案 5 :(得分:3)
我个人添加了以下代码。我使用Sys.info()和any()来获取唯一信息。
第一步是使用Sys.info()并找到您计算机的唯一标识符。
if(any(Sys.info() == "COMPUTER1")) {
setwd("c:/Users/user1/repos/project/")
}
if(any(Sys.info() == "COMPUTER2")) {
setwd("home/user1/repos/project/")
}
只需将计算机名称添加到if语句并添加正确的路径即可。只需为每台机器添加一个新的if。
对于复制,除非是特定用户,否则不会更改任何人的工作目录。