Interactivity: Quarto & Observable JS

Modified

February 19, 2024

This is a very basic example of displaying an interactive visualization using ObservableJS. Use the drop-down box to test how the plots and tables are reactive to user input.

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

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

The above example uses {r} code-chunks and the {haven} package to import labeled Qualtrics data. The SPSS data file is a .sav file with raw data, variable and value labels ingested via read_sav, wrangled with {dplyr}, and then visualized with client-side interactive ObservableJS {ojs} code-chunks. Using the RStudio IDE and Quarto, it’s easy to combine R and Observable code so that we can render this interactive page. (See the </> Code icon at the top of this page.)

Learn more below…

Transpose to arquero

Behind the scenes, when rendering this report, I use {r} code-chunks to import and wrangle the data. 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))
```

Simplified example

basic

The next code-chunk shows a very simple example of ObservableJS {Plot} code for visualization. This example is not interactive but it demonstrates 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 R. This way we can focus on using the {Plot} grammar and syntax that is very similar to {ggplot2} – see the above example. However, Observable JS is a complete and rich language of its own. So, just like {shiny}, we want to learn just enough to get the job done. That said, there is a case where a little more data wrangling is optimal. This is where {arquero} comes in. Arquero is used for data wrangling 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 we can coerce a data-type for the my_data$date vector by transforming a character data-type to a date data-type using Arquero’s .derive() function. Arquero’s .derive() function is similar to dplyr::mutate()

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

On this page, we use both {r} and {ojs} code chunks within one Quarto notebook. This shows how to present useful interactivity in a multilingual coding context.

Examples and documentation

See a very cool demo at the Quarto-Observable introduction page. Learn more about this exciting option at the Quarto-Observable JS Guide.