[R-SIG-Mac] Swift + embedded R

Bob Rudis bob @end|ng |rom rud@|@
Sat Jan 16 19:20:01 CET 2021


Hey folks,

In case there's any interest in using embedded R with Swift/SwiftUI,
I've started a blogdown series on that very thing.

Updates will be over at https://rud.is/books/swiftr/ & the associated
repo is at hrbrmstr/swiftr-book-examples

The book and repo are leading up to an eventual release of two
(Swift/C) packages that will make the bridge easier to integrate into
macOS Xcode Swift projects.

That library will have two modes. One will be the traditional way
embedded R works now with C code (Rf_…, SEXPs, etc).

The other uses a new/recent capability of Swift that makes the
language a bit more dynamic (at the cost of some type safety which is
sad but useful enough to make it cool).

That second mode will make Swift code like this possible:

    _  = try R.evalParse("options(tidyverse.quiet = TRUE )")

    // in practice this wld be called once in a model
    try R.library("ggplot2")
    try R.library("hrbrthemes")
    try R.library("magick")

    // can mix initialization of an R list with Swift and R objects
    let mvals: RObject = [
      "month": [ "Jan", "Feb", "Mar", "Apr", "May", "Jun" ],
      "value": try R.sample(100, 6)
    ]

    // ggplot2 ex. `mvals` is above, `col.hexValue` comes from the color picker
    // can't do R.as.data.frame b/c "dots" so this is a deliberately
exposed alternate call
    let gg = try R.ggplot(R.as_data_frame(mvals)) +
      R.geom_col(R.aes_string("month", "value"), fill: col.hexValue) +
// supports both [un]named
      R.scale_y_comma() +
      R.labs(
        x: rNULL, y: "# things",
        title: "Monthly Bars"
      ) +
      R.theme_ipsum_gs(grid: "Y")

    // an alternative to {magick} could be getting raw SVG from {svglite} device
    // we get Image view width/height and pass that to {magick}
    // either beats disk/ssd round-trip
    let fig = try R.image_graph(
      width: Double(imageRect.width),
      height: Double(imageRect.height),
      res: 144
    )

    try R.print(gg)
    _ = R.dev_off() // can't do R.dev.off b/c "dots" so this is a
deliberately exposed alternate call

    let res = try R.image_write(fig, path: rNULL, format: "png")

    imgData = Data(res) // "imgData" is a reactive SwiftUI bound
object; when it changes Image does too

All of the "R.…" calls are dynamically looked up in the embedded R session.

It's a WIP (~70% feature complete) and will be introduced in the
bookdown series and repo in a couple weeks.

It likely isn't super useful to a general audience (or perhaps only
useful to me :-) but the latest Swift 5 update made working with R
directly from Swift much, much easier than previously possible.

https://twitter.com/hrbrmstr/status/1344036731855769600?ref_src=twsrc%5Etfw
has a running example of the above code.

Cheers…

-boB



More information about the R-SIG-Mac mailing list