2  Using ggplot in Clojure with ClojisR

SciCloj logo
This is part of the Scicloj Clojure Data Scrapbook.

2.1 Setup

We will use ClojisR to call R from Clojure.

(ns using-clojisr
  (:require [clojisr.v1.r :as r :refer [r]]
            [clojisr.v1.applications.plotting :as plotting]
            [scicloj.kindly.v4.kind :as kind]
            [tablecloth.api :as tc]))

2.2 Plotting by calling R code

Let us load ggplot2 at the R runtime:

(r/library "ggplot2")
[1] "ggplot2"   "Rserve"    "stats"     "graphics"  "grDevices" "utils"    
[7] "datasets"  "methods"   "base"     

We will use the mpg dataset, which is part of the ggplot package.

(-> "mpg"
    r
    r/r->clj)

_unnamed [234 11]:

:manufacturer :model :displ :year :cyl :trans :drv :cty :hwy :fl :class
audi a4 1.8 1999 4 auto(l5) f 18 29 p compact
audi a4 1.8 1999 4 manual(m5) f 21 29 p compact
audi a4 2.0 2008 4 manual(m6) f 20 31 p compact
audi a4 2.0 2008 4 auto(av) f 21 30 p compact
audi a4 2.8 1999 6 auto(l5) f 16 26 p compact
audi a4 2.8 1999 6 manual(m5) f 18 26 p compact
audi a4 3.1 2008 6 auto(av) f 18 27 p compact
audi a4 quattro 1.8 1999 4 manual(m5) 4 18 26 p compact
audi a4 quattro 1.8 1999 4 auto(l5) 4 16 25 p compact
audi a4 quattro 2.0 2008 4 manual(m6) 4 20 28 p compact
volkswagen new beetle 2.0 1999 4 manual(m5) f 21 29 r subcompact
volkswagen new beetle 2.0 1999 4 auto(l4) f 19 26 r subcompact
volkswagen new beetle 2.5 2008 5 manual(m5) f 20 28 r subcompact
volkswagen new beetle 2.5 2008 5 auto(s6) f 20 29 r subcompact
volkswagen passat 1.8 1999 4 manual(m5) f 21 29 p midsize
volkswagen passat 1.8 1999 4 auto(l5) f 18 29 p midsize
volkswagen passat 2.0 2008 4 auto(s6) f 19 28 p midsize
volkswagen passat 2.0 2008 4 manual(m6) f 21 29 p midsize
volkswagen passat 2.8 1999 6 auto(l5) f 16 26 p midsize
volkswagen passat 2.8 1999 6 manual(m5) f 18 26 p midsize
volkswagen passat 3.6 2008 6 auto(s6) f 17 26 p midsize

Here is how we may generate a plot from R code:

(def plot1
  (r "(ggplot(mpg, aes(cty, hwy, color=factor(cyl)))
         + geom_point()
         + stat_smooth(method=\"lm\")
         + facet_wrap(~cyl))"))

Rendering as SVG:

(-> plot1
    plotting/plot->svg
    kind/html)
6 8 4 5 10 15 20 25 30 35 10 15 20 25 30 35 10 20 30 40 10 20 30 40 cty hwy factor(cyl) 4 5 6 8

Rendering as a bitmap image:

(-> plot1
    plotting/plot->buffered-image)

2.3 Plotting by calling generated R code

We may also plot by generating the R code from a Clojure form.

Let us require ggplot as a Clojure namespace.

(r/require-r '[ggplot2 :as gg])
nil

Now we can plot using code generation:

(-> (r/r+ (gg/ggplot gg/mpg
                     (gg/aes :x 'cty
                             :y 'hwy
                             :color '(factor cyl)))
          (gg/geom_point)
          (gg/stat_smooth :method "lm")
          (gg/facet_wrap '(tilde . cyl)))
    r
    plotting/plot->svg
    kind/html)
6 8 4 5 10 15 20 25 30 35 10 15 20 25 30 35 10 20 30 40 10 20 30 40 cty hwy factor(cyl) 4 5 6 8

2.4 Plotting by calling generated R code with Clojure data

We may further use ClojisR’s code generation with Clojure data.

Let us read the same mpg dataset. At the scicloj.metamorph.ml.toydata.ggplot namespace of metamorph.ml, we have Clojure copies of ggplot’s toy dataset, represented as tech.ml.dataset datasets.

(require '[scicloj.metamorph.ml.toydata.ggplot
           :as toydata.ggplot])

Now we can do the same, but pasing a Clojure dataset:

(-> (r/r+ (gg/ggplot toydata.ggplot/mpg
                     (gg/aes :x 'cty
                             :y 'hwy
                             :color '(factor cyl)))
          (gg/geom_point)
          (gg/stat_smooth :method "lm")
          (gg/facet_wrap '(tilde . cyl)))
    r
    plotting/plot->svg
    kind/html)
6 8 4 5 10 15 20 25 30 35 10 15 20 25 30 35 10 20 30 40 10 20 30 40 cty hwy factor(cyl) 4 5 6 8

Another example:

(require '[scicloj.metamorph.ml.toydata :as toydata])
(-> (r/r+ (gg/ggplot (toydata/iris-ds)
                     (gg/aes :x 'sepal_length
                             :y 'petal_length
                             :xend 'sepal_width
                             :yend 'petal_width
                             :color '(factor species)))
          (gg/geom_segment :size 5
                           :alpha 0.1)
          (gg/scale_color_brewer :palette "Set1"))
    r
    plotting/plot->buffered-image)

Reorganizing the code:

(-> (toydata/iris-ds)
    (gg/ggplot (gg/aes :x 'sepal_length
                       :y 'petal_length
                       :xend 'sepal_width
                       :yend 'petal_width
                       :color '(factor species)))
    (r/r+ (gg/geom_segment :size 5
                           :alpha 0.1)
          (gg/scale_color_brewer :palette "Set1"))
    r
    plotting/plot->buffered-image)
source: projects/datavis/ggplot/notebooks/using_clojisr.clj