Image source

Days 24-25: Trousers to the mast

A few days ago, I was playing around with cat gifs, and used this post that as a guide to help me draw the “very bored with irises cat graph” that is still giving me joy…

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.

The 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…

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:

library(here)
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:

 here("analysis","kalman.R")

On my machine, this command produces this as the path

[1] "/Users/dan/Dropbox/Research/DN_VanishingBandits/analysis/kalman.R"

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.

Avatar
Danielle Navarro
Associate Professor of Cognitive Science

Related