How to run params in R scripts from Clojure – #clojure #r #datascience #data #java

You can read the main post here.

Passing parameters into Rscript.

A Mrs. Trellis of North Wales writes….

There’s always one, isn’t there? The decent chap as a point though so let’s plough on with it now.

New R code

First a new R script to handle arguments being passed to it.

#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)

if(length(args)==0) {
 stop("No args supplied")
} else {
 print(args)
}

If I test this from the command line I get the following:

$ Rscript params.R 1 2 3 4
[1] "1" "2" "3" "4"

Okay, that works so far, now to turn our attention to the Clojure code.

The Clojure Code

Let’s assume we have a vector of numbers, these will be passed in the run command as arguments. So I need a way to converting the vector into a string that can be passed in to the sh command.

(defn prepare-params [params]
 (apply str (map #(str " " %) params)))

Which gives an output like this:

rinclojure.example1> params
[1 2 3 4]
rinclojure.example1> (prepare-params params)
" 1 2 3 4"

With a little amend to the run command function (I’m going to create a new function to handle it)….

(defn run-command-with-values [r-filepath params]
 (let [format-params (prepare-params params)
 command-output (sh "Rscript" r-filepath (prepare-params params))]
   (if (= 0 (:exit command-output))
     (:out command-output)
     (:err command-output))))

Running the example passes the string in to the R script.

rinclojure.example1> (run-command-with-values filename params)
"[1] \" 1 2 3 4\"\n"
rinclojure.example1>

Not quite going according to plan. We have one string of arguments meaning there’d be some parsing to do on within the R script. Let’s refactor this function a little more.

(defn run-command-with-values [r-filepath params]
 (let [sh-segments (into ["Rscript" r-filepath] (mapv #(str %) params))
       command-output (apply sh sh-segments)]
   (if (= 0 (:exit command-output))
      (:out command-output)
      (:err command-output))))

The (prepare-params)function is now useless and removed. Using the into function we create a single vector of instructions to pass into sh this includes the Rscript command, the filepath and mapping through the values in the parameters.

Instead of running sh on it’s own I’m applying the vector against sh. When it’s run against the R script we get the following output:

rinclojure.example1> (run-command-with-values filename params)
"[1] \"1\" \"2\" \"3\" \"4\"\n"
rinclojure.example1>

Now we’ve got what we’re after, separate entries being registered from within the R script. The R script will have to deal with the argument input, converting the strings to numbers but we’re passing Clojure things into R with parameters.

Mrs. Trellis, as the basics go, job done. I’m sure it could be done better. Each case is going to be different so you’ll have to prepare the vector for each R script you work on.

 

 

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: