Wednesday, February 15, 2012

Calling R from Scala

My main programming language is still R. Incanter, while a nice attempt, is definitely not anywhere close to allowing Clojure to be a replacement for R. The JVM is not suitable for the numerical programming I do, and I find myself spending too much time trying to figure out how to change the code to speed it up.

Thus, as I've started learning Scala, I want to make sure I've got the backup of easy interoperability with R. That's basically what I did when I started learning Clojure. Here is my attempt to do the same thing in Scala. I'm still a beginner, so I won't claim to be able to write good Scala code yet.

My preference when using JVM languages is Eclipse. For Scala, there is an excellent IDE available. I followed the usual instructions to install it. (There is plenty of information on the internet, but it's basically pasting the link they provide into Eclipse, clicking some buttons, and restarting).

I switched to the Scala perspective, started a new Scala project, and added a new file under src. I then started typing. I was really impressed with the Scala IDE. It's still early in this adventure, but based on what I'd read, I was expecting it to be a piece of garbage. It was incredible for the small things I did with it. I especially like how it points out errors while you type. It's just a pleasure to use.

To access R, I downloaded the two jar files that are made available for Rserve. I use Linux, so I opened R in a terminal window, did "library(Rserve)", then "Rserve()".

Back in Eclipse, I right-clicked on the project name, went to "Build Path", then "Add External Archives...". I chose Rengine.jar and then RserveEngine.jar. Those names appeared under "Referenced Libraries" below the project name.

After a few small mistakes, this is the program I came up with. (It's released under the GPL version 2 or greater if you're wondering.)

object rs {
  import org.rosuda.REngine
  import org.rosuda.REngine.Rserve.RConnection
 
  def main(args: Array[String]) {
    val c = new RConnection
    val d = c.eval("rnorm(10)")
    val e = d.asDoubles
 
    for (i <- 0 until 10) {
        println(e(i))
    }
  }
}

Edit: Scala has a better way to print an array than the C-style for loop that I used. You can replace the for loop with  

println(e.deep.mkString("\n"))

I chose "Run" from the menu, followed by "Run" again. After a brief wait (presumably for compilation), I got the following output:

1.1357939434863817
0.45168475066687624
0.8312101791389808
-0.8825102796935446
0.9597726735219193
0.5916220359121344
-0.8979526251577276
0.2217958737969706
-0.013414880990143055
0.021108802828942192

That's it! Super easy. I called R from Scala, had R generate 10 random numbers, shipped those random numbers back to Scala, and printed them out. I can now do anything with "e" that I would do if I had created the random numbers in Scala.

The only drawback is all the syntax. I'm resigned to the fact that most programmers think syntax is good.

6 comments:

P said...

Hi,

Did you manage to call Scala methods from R?
I tried to use rJava but didn't manage...

Best,
P

Rajiv Gangadharan said...

I tried it out and it worked like a charm, I am simplifying it further here.

object rs {
import org.rosuda.REngine
import org.rosuda.REngine.Rserve.RConnection

def main(args: Array[String]) {
((new RConnection).eval("rnorm(10)").asDoubles).map(println(_))
}
}

Rajiv Gangadharan said...

Doing a minor simplification further -

object rs extends App {
import org.rosuda._
import org.rosuda.REngine.Rserve.RConnection
override def main(args: Array[String]) = ((new RConnection).eval("rnorm(10)").asDoubles).map(println(_))
}

Anonymous said...

Where do you specify the host & port to connect to Rserve ? (What if Rserve runs in another host ?).

Thank you very much ! Nice post ;)

Anonymous said...

Amazing! This blog looks just likе my old one!

Ιt's on a completely different topic but it has pretty much the same layout and design. Great choice of colors!

My blog post: http://www.ares.com/

emoosh said...

شركة نقل عفش بالقصيم
شركة نقل عفش بالباحة
شركة نقل عفش بينبع
دينا نقل عفش بابها
نقل الاثاث بالمدينة المنورة
ارخص شركة نقل عفش بمكة
شركة نقل عفش بالخرج
شركة نقل عفش بالبقعاء