OMG THIS IS SO COOL 🎈🎉🎂🍷 pic.twitter.com/h0A0yd1Wyc— Danielle Navarro (@djnavarro) May 17, 2018
At the top Daniel Hadley’s post, however, I noticed the use of the
here package to avoid having to set a working directory. The amount of aggravation that I could have been saved had I known about this trick years ago is just… sigh.
here package is deceptively simple, but offers a solution to the annoying problem that almost everyone runs into eventually - writing an R script that specifies a file relative to a location on your computer This is pretty annoying when you move files around on your computer, or worse, try to share your code with other people…
@JennyBryan) December 5, 2015
If the first line of your #rstats script is “setwd(…” I will come into your lab and SET YOUR COMPUTER ON FIRE.— Timothée Poisot (@tpoi) April 13, 2016
checks her code
Oh dear. Well, I certainly don’t want my computer set alight. Besides this annoys me too. I’ve tried to solve this on my own in a few different ways over the years, and nothing has ever felt very satisfactory. Maybe this time…
Trousers to the mast
HUMPHREY: Delivering a speech is just a formality you have to go through in order to get the press release into the papers. We can’t worry about entertaining people - we aren’t scriptwriters for a comedian. Well, not a professional one, anyway. No, the point is that the speech said the right things.
BERNARD: But why does it have to be said in public?
HUMPHREY: Well, it’s vital. Once the speech is printed, the Minister is committed to defending us in front of Select Committees and things.
BERNARD: But he defends us anyway.
HUMPHREY: Only to a point, Bernard. Once something goes wrong, the Minister’s first instinct is to rat on his department. So we write him a speech to get him to nail his trousers to the mast.
BERNARD: You mean, nail his colours to the mast?
HUMPHREY: No, nail his trousers to the mast. Then he can’t climb down.
I started using
here for a project and was an instant convert. The passage above from Yes Minister somewhat indirectly explains why. Here’s what happened when I started looking into it:
… okay, this looks cute … Doesn’t seem like a lot of effort and it solves a mildly annoying problem … [Reads a bit] … Hm, so all I have to do is create an empty file called
.here in my project root directory? Then I can use
here() to specify paths relative to that root? Fair enough … I need a post for today and I’m too tired to continue with the metaprogramming stuff … okay I’ll do a post on
here … I suppose I’ll use one of my existing projects as an example … Hm… the file structure to my project is going to make it a pain to use
here … Later on when I publish this as an OSF repository all my files will move relative to he project root and then all my links will break … this package is stupid … no, wait, that’s not right … the problem is that I haven’t been thinking about how this project will look when it gets archived … and that’s going to be a nightmare in a few months time when I need to revisit this … huh 💡 … maybe I need to be more disciplined in how I organise and document my projects…
At that point I tidied up the file structure to the project, improved the documentation in anticipation of future archiving, and then created a
.here file. The mere act of being asked to commit to the location of the project root, and in doing so define file paths within a relative to that root had a huge effect on how I thought about my project, and I’m much more confident that I’ll be able to make sense of what I’ve done when I revisit it later on.
So while I wish I could say that “the first thing I did was created an empty file called
.here in the project root directory” the truth of the matter is that “the first thing I did is think carefully about how my project to be organised”.
As Sir Humphrey would put it, I nailed my trousers to the mast.
Using the package
From that point onwards, using the package was really simple. I created the
.here file in my project root directory:
As it happens I could have done that within R using the
set_here function but honestly I think I prefer doing it from the file explorer. Now that I’ve created the
.here file, loading the package from any folder that falls within the project will give me this message:
here() starts at /Users/dan/Dropbox/Research/DN_VanishingBandits
That’s nice. I am immediately notified of which project I am working on and where the root directory is for that project. That said, I also have the joy of being deadnamed by my own laptop 😞 which I put up with because I’m so paranoid about file paths that I refuse to risk changing the user home to
/Users/dani. Eh, whatever: “Dan” works as a short form of “Danielle” right?
In any case, the important thing is that I can now use the
here() function to specify all my file paths relative to the project root directory. So for instance, I have a file called
kalman.R in the
analysis folder, which I can refer to it like this:
On my machine, this command produces this as the path
but of course if I move the entire “vanishing bandits” project to a new location or onto a new machine, it would look different. That’s pretty handy.
From little things big things grow
The idea of including a
.here file in the project root directory and then letting
here() do all the work is really appealing to me. Not only does it make the code more portable, I think it’s a nice little nudge that encourages me to think a little harder about how I organise my projects. Because paths should all be specified relative to the
.here file, I find myself wanting to make sure I don’t start referring to files outside of the current project, and wanting to make sure I have a sensible directory structure from the beginning. It also makes me think carefully about how to delineate projects. When does one project split and become the next? Which papers fall within the same project? They aren’t always easy questions to answer, but I think I end up doing better work when I ask them.