Skip to main content

Comparing Python Interactives to R Shiny

 

This is a companion to my previous blog post, where I compared popular Python libraries for creating interactive figures.  Here I will use the Shiny library in R and provide a narrative of my experience transitioning from Python interactives to R and Shiny.  As a quick refresher, my goals from the previous post were to create an interactive figure that

  • shows COVID-19 cases vs. time (while displaying the date correctly),
  • allows zoom and pan on the plot,
  • contains customizable tooltips to show the data values when the mouse hovers over the plot,
  • uses a dropdown menu to choose the country,
  • uses a menu to choose which columns I want to plot (for a given country), and
  • exports directly to a .html file for use on a personal website (without needing any other service).

Going from Python to R and Shiny

If you’ve read any of my previous blog posts, you’ve probably gathered that I default to Python for most of my data analysis needs, and I often turn to Python first for data visualization.  I learned Python around 2010-2011.  As an astrophysicist by training, I’ve encountered and created code in Python, IDL, C/C++, Fortran, IRAF, Javascript, and occasionally Java.  I had heard of “R”, but more like one hears about some exotic animal – you’ve read something about it on the internet or in books but don’t know anyone who has seen it in the wild, and frankly you’d be a bit wary of getting too close in the unlikely event that you did encounter it personally.

When I started in the RCS group, I quickly learned that many of the other amazing research departments at Northwestern use R as their default data analysis/visualization language.  So, last September I set out to learn R, at least a little bit, so that I could help other folks getting started with R code and also for my own edification.  As a Data Visualization Specialist, I focused mainly on ggplot and manipulating dataframes; I haven’t yet delved deeply into the myriad of statistical analysis packages available in R (though I will get there!).

After getting past the use of “$” (to access columns in a dataframe; df$column in R is the equivalent to df[column] in Python’s Pandas package) and also “<-” (assigning the value on the right side to that on the left; x <- 1 would be written as x = 1 in most other languages), I have found that much of my current understanding of Python and other languages transfers decently well to R.  Many of my data analysis/visualization tasks could likely be accomplished in either Python or R.  R is more focused on statistical analyses of dataframes, while Python is more “general-purpose” and enables a broader landscape of applications.  For a few months I’ve been slowly learning R in my spare time, and I recently progressed to interactive plotting with Shiny.

For those of you who have a Python background and have been curious about R, I can attest that it is not as big of a hurdle as you may fear.  In particular, the Shiny library in R provides a fairly easy-to-use alternative to the various Python libraries (e.g., Bokeh) for creating interactive figures.  Below, I walk through the basics of creating an interactive plot in Shiny and provide some thoughts comparing R-Shiny and Python.

The typical Shiny app

I started by reading and working through Shiny’s getting started webpage, which I would recommend to anyone embarking on their first Shiny app.  There’s also a very nice tutorial with multiple lessons on the Shiny website.  Since they do such a great job, I won’t go through all the details here, but I will provide a summary.

A typical Shiny app will have a few sections with a skeleton that looks like this:

R provides easy functions to create essentially any type of input element that you may want for the sidebarPanel.  I started with a dropdown menu, created using selectInput;  you can find documentation here, and if you scroll down on that linked webpage to “See also”, you’ll find a list of other input elements to choose from.   I was very happy with how easy it was to create the dropdown; I simply created a vector (which is similar to a Python list) with the values I wanted in the dropdown and fed that into selectInput.  You can also define your vector to specify both the dropdown label and value (which is often helpful if you want to use the dropdown value, e.g., to access a column in a dataframe, but you also want to include human-readable words for the actual dropdown menu options shown on the page).

The selections from the sidebarPanel are accessed through the input variable within the server function.  For instance, if you had a vector called columns that contained all the available columns in your dataframe and then created the following sidebarPanel:

you would access the value from that dropdown within the server function as input$column .

Within the server function you could then use the result of that dropdown input to generate a plot and assign that to a key in the output variable.  In my example, I wrote an additional function called generate_plot to produce my plot and assigned that to output$plot with the following code.

Back in the ui function (which also contains sidebarPanel), you have access to the output variable, e.g., to render the plot within the mainPanel as follows:

You can view the full code on my GitHub repo in the file app.R.  You may enjoy comparing this to the code I wrote to produce similar figures using Python libraries within this Jupyter notebook.   Each has its own format and code structure for defining the various components.  I consider Shiny to be very straight-forward in comparison, and for those who know a little of both R and Python, Shiny may be the easiest tool to learn.  Furthermore, less code was required for this Shiny app than nearly all of the Python packages, except maybe Altair.

Generating an interactive figure with tooltips

I initially generated my figure using standard ggplot2, which is a great plotting package for R and uses the “Grammar of Graphics” to build a plot in layers by adding together (using “+”) all the components that you want in your figure.  Generically, you’d start with something like “data + type + formatting”, where,

  • “data” represents the call to ggplot that, e.g., contains your dataframe and defines the columns you will use for the x and y axes,
  • “type” represents functions that define whether you plot points, lines, etc., and
  • “formatting” represents functions that might include axes scales and labels, the plot background color, plot title, etc.

I wanted to also include the ability to pan and zoom and to enable tooltips that appear when the user moves the mouse over a point or line.  Googling quickly brought me to ggplotly : a convenient wrapper for ingesting a ggplot2 figure into Plotly.  Plotly is a very versatile tool for creating interactive figures in a variety of coding languages, and comes with pan, zoom and tooltips built in.   (You can read my previous blog post for more information.)

I was very impressed with how easy it was to convert my ggplot figure into ggplotly (even if I didn’t know anything about coding a Plotly figure).  Here are the steps I took within Shiny to produce the Plotly figure after already having a working ggplot version:

  1. When generating the plot, I assigned my ggplot to a variable p and then called ggplotly(p).
  2. Within my server function, I changed renderPlot to renderPlotly.
  3. Within my ui, I changed plotOutput to plotlyOutput.

And it all simply worked!  I had a Plotly figure with all the usual bells and whistles (e.g., tooltips, ability to zoom, pan, save as png, etc.) within my Shiny app.  It is a little unsatisfying that the easiest way to create my interactive figure in R Shiny was to pivot to using a different library altogether (Plotly).  Nonetheless, the ease of transitioning from ggplot to Plotly meant that I could use ggplot’s relatively easy and elegant code structure without having to specifically code a Plotly figure, which can be a bit cumbersome in certain use cases.

Deploying my Shiny app for the world to see

There are various ways that you can share your Shiny app with others, and this webpage from Shiny provides excellent information.  I usually share these kinds of interactive plots by generating a .html file and hosting that on GitHub pages.  However, Shiny doesn’t have that option.  There are various ways that you can host your code online (e.g., on GitHub), and then anyone with R installed on their local computer can download and run your app easily (e.g., with the runGitHub command from the Shiny library), but that is somewhat unsatisfying because many people don’t have R installed (and either don’t want to or don’t know how to do so).

The easiest solution is to use shinyapps.io.  This is a free service where you can host your app, and others can access it as a website (without having to download anything or install R on their machine).  I tried this for the first time for this project and was similarly impressed by how easy it was to set up.

You may ask, as I did, “Why can’t Shiny just output a .html file, for instance like Plotly or Bokeh?”  But I realized that this may be the wrong question.  The fact that Shiny does not jam everything into a .html file has its own benefits.  Probably the top benefit is that your data is not exposed to the world in the same way that it is when using other tools.  Though your figure is visible on the frontend (e.g., in your friend’s browser), the underlying data used to generate the figure is only available on the backend (e.g., on the shinyapps.io server).  In certain research areas, e.g., medical fields where confidentiality is critical, keeping the data private and inaccessible is essential.

Also, note that R has other tools for making .html files, such as R Markdown, which can include html widgets.   This particular project is probably better suited for Shiny, but I encourage you to also explore R Markdown for your needs.

The finished product and how it compares to Python interactives

I went in with some trepidation and came out thoroughly impressed with Shiny.  Despite being a beginner in R and having never used Shiny before, I was able to create a usable interactive Shiny app in a few hours.  A live version of my Shiny app is embedded above and also available on shinyapps.io.  The full code is available on my GitHub repo.

How does this Shiny app compare to the various interactive Python figures I created in my previous post?  In that post, I concluded that Bokeh, Plotly and Altair are all excellent and versatile Python packages for producing interactive figures.  Shiny is a valuable alternative to these packages for those of you who either know R or are willing to spend a little time learning R.

  • The functionality of the Shiny figure is essentially identical to those produced by Python. I encourage you to test that yourself by comparing the figure embedded above to those embedded in my previous post.
  • Creating the dropdown menus (and other widgets) and allowing these inputs to change the figure is refreshingly easy in Shiny and certainly easier than some of the Python tools.
  • In Shiny, you only need to know R, while for some of the Python packages (e.g., Bokeh), you need to know Python and Javascript to truly harness the full potential.
  • Shiny covers nearly all the criteria that I set in my previous blog post and required minimal lines of code, far less than some of the Python packages (e.g., compare my app.R script for this Shiny app with the code in this notebook for each of the Python packages).
  • The only feature from my list that Shiny lacks is the ability to export directly to a .html file.  However, it turns out that there are good reasons for this — and for some people this will tip the scales in Shiny’s favor.   It is also easy enough to use shinyapps.io to host the app that I think this is a non-issue.
  • Also note that each tool has its own default look (though some customization is possible);  this can be another deciding factor on which tool you prefer to use.

I personally look forward to learning more R and Shiny, and I hope that this blog post has given you the tools and motivation to get started using Shiny as well.

Nov. 2023 update: There is now Shiny for Python!  If you are interested, please read my other blog post.

As usual, if you have a project in mind or want help developing an interactive figure (or have any other data visualization need), I’d be happy to work with you.  Please click here to submit a consult request.