kjo kjo - 2 months ago 10
R Question

Simple yet maintainable code re-use

Let's say I have a tiny (3-4 lines) function that I tend to use a lot.

Since it's so small, it's easy to copy-paste it into every source file that needs it, but copy-paste is not a maintainable form of code re-use.

Instead, I'd like to put this function in its own file, and somehow import it from other source files as needed.

I have found only two ways to do this so far:


  1. create an R package for my function, install it in my R library, and have client code run, e.g.
    library(myfunction)
    ;

  2. have client code execute
    source("path/to/my/function.R")
    .



(The first option strikes me as very heavy-handed for the simple use-case I have in mind. At the moment, I don't intend to submit this function to CRAN, or even to share it with anyone else. All I want to do is use it from my throwaway R scripts.)

Is there some other way to do this?




In Python, for example, I can put the tiny function in some file:

# hello.py

def hello():
print "hello, world"


...and put this file in a directory in my
PYTHONPATH
variable. Then, to use the function in any script
some_script.py
, all I need to do is

# some_script.py

import hello

hello.hello()
# hello, world


I'm basically looking for the closest equivalent to this in R.

Answer

I think you may be pleasantly surprised at how simple it can be to make a package for your own personal use. Keep in mind that you can build and install a package without it even remotely satisfying CRAN's requirements.

Just out of curiosity, I built a package that is operational on my machine and did it in less than five minutes. It has exactly one function.

Here's what I did.

In R I ran

package.skeleton(name = "OneFunc", path = [package_path])

Next, I created a .R file in the [package_path]/R and put in my function definition. To be explicit, here is exactly what is contained in my file.

my_useful_function <- function(x){
  x^2
}

I then went back to R and ran

devtools::install_local([package_path])
library(OneFunc)
my_useful_function(3)

which returned the value 9.

So, you can make a quick a dirty package that makes it very easy to load one (or several) functions without doing all the work of building a CRAN-suitable package.

Advantages:

  1. Clarity- you don't have the disadvantage of Dirk's answer because you still have to write library(OneFunc) in your code. So at least there's some indication that you've done something.
  2. It's barely more work that source, and you don't have to recall the directory every single time (only when you reinstall the package)
  3. It will easily extend into loading more than just the one function. All you need to do to add another function to OneFunc is drop the file in the R subdirectory and reinstall the package.

Disadvantages:

  1. No documentation. And worse, because you loaded a package through library it will look to others like there should be documentation. Honestly, I'd prefer this to a function showing up out of nowhere because it is in your /.Rprofile, but that's a matter of preference.

But seriously, it took me three times as long to write up this response as it did to make that bare bones package. I think you would find it worth your while.