Logo

The Data Daily

A beginner's guide to using Observable JavaScript, R, and Python with Quarto

A beginner's guide to using Observable JavaScript, R, and Python with Quarto

There’s an intriguing new option for people who want to do data-wrangling and analysis in R or Python but visualization in JavaScript: Quarto.

This article shows you how to set up a Quarto document to use Observable JavaScript, including how to pass data from R or Python to an Observable code chunk. In Part 2, you'll find out how to learn Observable JavaScript with Observable notebooks—and why that's worth doing even if you only plan to use JavaScript in Quarto. Part 3 gives you the basics of data visualization with Observable JavaScript, including how to make your plots interactive.

Quarto is an open-source technical publishing platform from RStudio that natively supports Python, R, Julia, and Observable JavaScript—a JavaScript flavor designed for data analysis. Using Quarto with Observable could be a compelling option for R and Python users who also want to use JavaScript. Here are a few reasons why:

Why visualize in Observable if you already generate plots with R or Python? One reason is that Observable has interactivity built in. Using Observable, there are simple ways to add interactive filters on your data that control what appears in tables and graphs.

Additionally, Quarto’s rendered HTML files can be hosted on any web server or opened locally with a simple browser, with no separate language or framework installations required. That’s not the case for options like Shiny for R or Dash for Python (alpha Shiny for Python can run without a Shiny server, but it's not yet production-ready). Using Quarto with Observable offers an elegant workflow if you want to combine data analysis in Python and R with reactivity.

Finally, Observable was set up with collaboration in mind, so it's fairly easy to find and use someone else's open source code.

Bottom line: If you want to quickly code an interactive report or analysis and email it to colleagues or host it on an intranet that handles HTML files, integrating R or Python and Observable JavaScript in Quarto could be a great choice.

Quarto is a separate software application and not an R or Python package. If you use R and have an up-to-date version of RStudio, Quarto software is bundled in. If you use Python or R in Visual Studio Code (VS Code), download the Quarto software application from the Quarto Get Started page and the separate VS Code Quarto extension.

To incorporate Observable JavaScript in a Quarto document, use  for an Observable code chunk, as opposed to  for R code and  for Python. Chunk options are preceded with a  in R and Python but  for Observable. Here's an example:

The above code creates an code chunk that will execute code within it but not display that underlying code in the final document. 

Both RStudio and VS Code offer code completion help when writing the YAML header at the top of a Quarto document. This header defines the file metadata and various document-wide options. However, you won't find the same kind of robust IDE support for things like executing single cells or code completion for Observable code chunks as you would with R and Python.

You can import, wrangle, and analyze data in R or Python and then send those results to Observable with the  function. “That’s the magic,” said Maya Ganz, a developer at Atorus who was an intern at RStudio several years ago. It “dramatically reduces the barrier to entry” for R and Python users to add JavaScript to their workflow.

To send wrangled data from R or Python to Observable Javascript, the syntax is:

Note that  also works in Python code chunks. As of this writing, however, you can’t run an R or Python chunk with  interactively in RStudio. If you try clicking the chunk’s run icon, it will fail. For now,   only works when Quarto renders the entire document at once.

An RStudio spokesperson said that they hope to have an improved experience in the future, but because it's easy to get that user experience (UX) wrong, for now they've focused on entire-document execution.

There is one more step to use data from R or Python in Observable: .

JavaScript visualizations usually use a different data format than the rectangular data frames typically needed in R or Python. For instance, below is a partial example of data for a multiline graph from the Apache ECharts website:

That is an array of JavaScript objects, not the rows-and-columns format used by libraries like ggplot2. Fortunately, there’s a single function, , that will turn R or Python data frames sent to Observable into the format Observable needs. If you forget to use  on data imported with , and then try to use that data in Observable, you may get an error like this one:

If you see that error, check whether you’ve used  on data imported with .

You can create a new transposed object within an Observable code chunk with something like this:

Then, use  in all your subsequent functions. Or, you can refer to  each time you access your data set in Observable.

Finally, note that  and  are specific to Quarto documents, not Observable notebooks hosted on the Observable web platform at ObservableHQ.com. The hosted notebooks don’t run R or Python code.

You can also import external data directly into Observable. Here’s the syntax for importing a local CSV file with Observable’s  function inside an code chunk:

The  asks  to guess the column types. To properly parse the data for use, be sure to include the  after  for a CSV file. 

Several other formats work with , too, such as .

For a CSV file hosted online, you can use the D3 JavaScript library’s  function:

D3.js is included by default in Quarto’s Observable setup.

In a Jupyter notebook or R Markdown file, code cells run from the top down when you render a document. The only exception is if you manually trigger cells individually in a different order instead of executing the whole file at once. This means you can’t have a cell which calls a variable, x, before a cell that defines x. So, the following will throw an error:

In addition, you can’t call a function you’ve written above the cell that created the function.

In Observable, though, cells run in the order they’re needed—what’s called a reactive dataflow. That means you can refer to x with  in a cell  above the cell that defines x.  And, you can use a custom function at the top of your notebook but define it at the very end. That’s part of Observable’s built-in reactivity: if a variable's value changes in one cell, all cells using the variable get updated, not only the ones below.

But while this is handy for interactivity, it also means you can’t define a variable more than once; not unless it’s within a code block in the same cell, such as an statement surrounded by braces. Otherwise, Observable doesn’t know which should run first. 

There are a few more differences between Observable and “vanilla” JavaScript, which you can read about in the Observable’s not JavaScript documentation. Next: Learn Observable JavaScript with Observable notebooks.

Images Powered by Shutterstock