Tyler Smith bio photo

Tyler Smith

Plant taxonomist
Adjunct professor
Field botanist

Email Twitter Github Stackoverflow

I got lots of response on twitter to my previous post on the use of setwd in R. Most of it was positive, but three very valid criticisms were raised that I’d like to address.

The first, and ultimately most important, came from Joran Elias:

Too right! I wrote as if there was one true way to use R, and that suggests you need to join a particular in-crowd to be worthy. I can understand how that attitude will alienate some. Especially considering my point was most emphatically that there was one correct way to use setwd (don’t!), and clearly that’s not true. Particularly in light of the second issue, raised by Tim Lucas:

This was part of a longer exchange that revealed that Tim and I had been talking past each other on this key point. I use the Emacs Speaks Statistics (ESS) package to run R from the Emacs text editor. The first thing that happens when I start up R is that ESS prompts me for my working directory. So I personally never touch setwd myself, because that dirty work has been delegated to Emacs. RStudio provides this same service through the file browser window.

However, for people that don’t use an interface like this, they have to explicitly call setwd themselves to tell R where to find their files. This is of course correct and entirely appropriate. I would still argue that the call to setwd should not appear in your actual script file, but if it was the first line it should be relatively clear to collaborators what you were doing.

I also got some email raising this issue, so to be clear, everything I said in my previous post assumes you have some way to get R running in the appropriate directory, and that may well require you to use setwd.

Finally, some examples of setwd that are useful and don’t undermine portability. From Gabor Csardi:

This is the function he refers to:

with_wd <- function(dir, expr) {
  wd <- getwd()
  on.exit(setwd(wd))
  setwd(dir)
  eval(expr, envir = parent.frame())
}

Very tidy! with_wd saves the current working directory and moves to a new (temporary) directory. Once there, it executes your code, presumably creating a bunch of temporary files in the process. On completion, it restores the original working directory. Combining this with a call to tempdir gives you a nice way to execute code that produces a lot of temporary files without cluttering up your working directory.

Another good use of setwd from Tony Fischetti:

With a little thought I’m sure we could come up with more exceptions to prove the rule that setwd should never be used. I will leave it at this: before you use setwd in your scripts, consider the impact it will have on the portability of your code, both to your collaborators, and to future you, who may have to run it on another computer. If there’s another way to accomplish what you need, setwd is probably the worse option.