Interactivity: Quarto & Observable JS

Author
Affiliations
John R Little

Duke University

Published

May 23, 2023

Interactivity (Observablejs)

This is a very basic example of diplaying an interactive visualization using ObservableJS.

Show the code
```{ojs}
//| code-fold: true
//| echo: fenced

my_survey_filtered = my_survey
  .filter(aq.escape(d => d.my_question == radio_2))
  .groupby('my_question', 'response', 'rnumber')
  .count()
  .orderby('my_question', aq.desc('rnumber'))
  
Plot.plot({
  marginRight: 140,
  y: {
    axis: null,
    domain: d3.sort(my_survey_filtered, d => -d.rnumber).map(d => d.response)
  },
  x: {
    grid: true
  },
 marks: [
    Plot.barX(my_survey_filtered, {y: "response", x: "count"}),
    Plot.text(my_survey_filtered, {
      x: "count",
      y: "response",
      text: "response",
      textAnchor: "start",
      dx: 6
    })
  ]
})
```

Download

Transpose to arquero

Behind the scenes, when rendering this report, I use {r} code-chunks to import and wrangle the data. Just like I did in code how you like, I’m importing and wrangling my data with a quarto-friendly code language. Then I transpose my data frame into an OJS object.

```{ojs}
//| echo: fenced
my_data = aq.from(transpose(trade_df_ojs))
my_survey = aq.from(transpose(my_df_tall_ojs))
```
Reveal code: click the </> Code icon

This page reveals the observablejs {ojs} code-chunks. However, this page demonstrates using {r} and {ojs} together in the same quarto-document. You can scroll to the top and click the </> Code icon to see all the code. Or click the GitHub icon in the navigation bar. Quarto makes it easy to include these features.

One more example

The next code-chunk shows a very simple example of ObservableJS {Plot} code for visualization. This example is not interactive, to show the remarkable similarity to {ggplot2} syntax.

plot

```{ojs}
//| echo: fenced
Plot.plot({
  marks: [
    Plot.ruleY([0]),
    Plot.lineY(my_data_wrangled, {
      x: "date",
      y: "sales",
      stroke: "business"
    }),
  ]
})
```
↥ Look up!

Notice the crispness and clarity of the simple non-interactive plot above. Observable Plot shows well on the web!

Arquero data wrangling

Derive date

Aside from the {dplyr} wrangling that I did in the background of this code notebook, I still needed to parse the date fields. Arquero to the rescue.

Arquero! Now what is that? Observable JavaScript is its own coding language and we can minimize the learning curve by keeping our data wrangling within our favorite coding language. Then we can focus on using the {Plot} grammar and syntax, which is quite similar to {ggplot2} – see the above example. However, Observable JS is a complete and rich coding language of its own. But just like {shiny}, we want to learn just enough to get the job done. Still, there’s always an edge case where a little data wrangling is optimal. This is where {arquero} comes in. Arquero is used for data transformation and is easy to learn because it was inspired by {dplyr}. Show the code for the first plot on this page and you’ll see the similarity to {dplyr}.

Below I parse a data type using {arquero}.

```{ojs}
//| echo: fenced
my_data_wrangled = my_data
  .derive({  date: d =>  op.parse_date(d.date) })
```

Observablejs libraries

By convention, observable libraries are loaded at the bottom of a code notebook. You can read more about observablejs at Observablehq.com. By way of a teaser, I didn’t have to use {r} to wrangle the retail data. I could have imported the data directly from observable. Such as ….

> import { data, advancedDate } from "@observablehq/monthly-retail-trade-report-data"

But on this page, I’m demonstrating how we leveraged {R} and {ojs} code with Quarto, so that I can present useful interactivity and demonstrate multi-lingual coding using a Quarto notebook.

```{ojs}
//| echo: fenced
import { aq, op } from '@uwdata/arquero'
// import { data, advancedDate } from "@observablehq/monthly-retail-trade-report-data"
import {button as downloadButton} from "@jeremiak/download-data-button"
```