Reticulated Shiny

[This article was first published on R Views, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

RStudio recently announced the reticulate package, which is designed to help R users inter-operate with Python code. I was immediately excited by this announcement. In a past life, I worked with a team at the National Renewable Energy Lab (NREL) on vehicle simulations. Their models could predict MPG for vehicles based on driving routes. At the time, I had wanted to build a web app that would allow users to predict MPG for different vehicles based on their daily commutes. Unfortunately the model was written in Python, but my web application experience was limited to Shiny. I didn’t want to rewrite the model in R, nor did I have time to learn a Pythonic web framework. Nothing came of the idea…until today*!

Using reticulate, I was able to easily build a Shiny application that used my colleague’s Python code. I also used Python’s Google Maps API client. While R packages exist to work with Google Maps, the Python client is maintained by Google and is simple to access with reticulate.

Checkout the live application and source code.

Screen shot of a reticulated Shiny app

This post covers a few details and tips for using reticulate, and creating reticulated Shiny apps.

Getting Started

To use reticulate you’ll need to setup Python and any Python dependencies required by your project. We recommend using virtualenv and pip, which are well documented for newcomers.

Once your Python environment is setup, you’ll need to tell the reticulate package to use the environment. reticulate provides the helper functions: use_virtualenv and use_conda. These functions should be called before any other reticulate functions are used. For example, I included the following lines at the top of my app.R file:

library(reticulate)
use_virtualenv('/path/to/myhybrid-project', required = TRUE)

Once your environment is setup, there are two methods for interacting with reticulate code.

Method 1: “Sourcing”

In my case, the Python code my colleagues developed was available in a single Python file. The file consisted of a number of Python functions. To use those functions, I ran source_python('../subdir/with/python-model.py').

Once sourced, I was able to call the Python functions directly as R functions. For example, one of the functions defined in my Python file was sim_drive. The function signature in Python looks like:

def sim_drive( cyc , veh ):

cyc and veh are both Python dictionaries. The function normally returns a complex Python dictionary containing numeric values as well as numpy arrays. In my R code, I can invoke sim_drive as an R function:

results <- sim_drice(cyc, veh)

In my case, cyc and veh are R data frames and results will be an R list. reticulate handles all of the conversions between R and Python automatically. (This worked the first time I tried it; I was literally giddy!).

If your Python file doesn’t contain functions, but also creates objects, use py_run_file instead of source_python and then access the Python objects using py$object.

Method 2: “Importing”

The second method for writing reticulated code is to import Python objects and write R code that uses those references. This method is helpful if you don’t have existing Python files, but instead want to access Python classes or methods.

For my app, I wanted to make use of the Google Maps Python client maintained by Google. The Google help documentation provides sample Python code to query the Directions API:

import googlemaps
import os

from datetime import datetime

gmaps = googlemaps.Client(key=os.environ['DIRECTIONS_API_KEY'])
  
def get_route(start, end):
  route = gmaps.directions(start,
                                end,
                                mode = "driving", 
                                departure_time  = datetime.now())
  return(route)

Using reticulate, I was able to write similar R code that utilized the same Python objects:

googlemaps <- import('googlemaps')

gmaps <- googlemaps$Client(key = Sys.getenv('DIRECTIONS_API_KEY'))
  
get_route <- function(start, end) {
  
  route <- gmaps$directions(
            start,
            end,
            mode = "driving", 
            departure_time  = Sys.time())
  return(route)
  
}

I was able to swap some of the Python components with R code; for example I used Sys.time and Sys.getenv in place of datetime and os. reticulate’s flexibility lets you interweave R and Python code.

The resulting routes object is a complex nested list. I opted to use purrr to process this list, but if you were familiar with Python tools, you could continue to write reticulated code. reticulate enables you to pick the pieces from each language that you like best. The remainder of the application logic is written in R, including the use of SMA for smoothing and a fair subset of the tidyverse for tidying and plotting data. I’d be remiss if I didn’t include a brief shout-out to the shinymaterial package for providing an appealing and easy-to-use shiny theme.

Deployment

Like any Shiny application, a reticulated Shiny app has to be deployed in order for others to leverage the app. Reticulated Shiny apps can be deployed like regular Shiny apps, but take care to ensure that the deployment server has the same Python environment.

Parting Thoughts

reticulate helped me accomplish a task that I had been day dreaming about for years. You don’t need to be a Python expert, but you do get many of the benefits. The reticulate website explains that the name of the package comes from the interweaving color pattern found on reticulated pythons. I found interweaving Python and R to create reticulated R code powerful and enjoyable. I can’t wait to see more examples of this new breed of code!

*Disclaimer

Access to NREL’s FASTSim model used in this demo is available here. The Shiny application was developed independently by RStudio as a demo using the freely available FASTSim model. The application was not written in conjunction with the National Renewable Energy Lab (NREL), nor is the application endorsed by NREL. The results presented in the application are not to be used for accurate vehicle comparisons. RStudio is NOT RESPONSIBLE for the accuracy or reliability of any results presented in the application.

To leave a comment for the author, please follow the link and comment on their blog: R Views.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)