robservablequartoojs

Passing dates from R chunk to ojs chunk using ojs_define in Quarto


I am using R and ojs code chunks in a quarto document where I do data manipulation in R and the pass the data frame to the ojs chunk by using the ojs_define function.

My issue is that date seems to be interpreted as string in ojs chunk. The result is bad formatting in plots.

Any tips on how to pass a date from r to ojs in a way that the ojs plot function recognizes it as a date?

Example:

---
title: "Code example"
format: html
editor: visual
execute:
  echo: false
  warning: false
---

```{r}
#Some data with a date column
library(tidyverse)

df<-data.frame(day=seq.Date(from=as.Date('2023-01-01'), 
                            to=as.Date('2023-06-15'), 
                            by='days'))%>%
  mutate(values=rnorm(mean= 10, sd=2, n =n()))

#Passing this to ojs through ojs_define

ojs_define(plot_data=df)
```


```{ojs}

Chart = Plot.plot({
  marks: [
    Plot.line(transpose(plot_data), 
      {x: "day", y: "values"}, 
      { stroke: "black" }
    )
  ]}
)
```

Solution

  • Since dates are being parsed as string when passed through the ojs_define, we can transform back the string-dates type to datetime type in the ojs chunk.

    Here we will use d3.timeParse to create a datetime parser and will use the Arquero library (inspired by the design of dplyr) to derive (i.e mutate) the day column to have datetime values.

    Two things to note here,

    1. Arquero work with data tables. But the plot_data is of JSON format. So we need to transpose it to convert it to an array of objects which then passed to aq.from to convert as table.

    2. To use that parser within derive, we need to wrap d => parse(d) with aq.escape

    ---
    title: "Code example"
    format: html
    execute:
      echo: false
      warning: false
    ---
    
    ```{r}
    library(dplyr)
    
    df <- data.frame(day = seq.Date(
            from = as.Date('2023-01-01'),
            to = as.Date('2023-06-15'),
            by = 'days'
          )) %>%
      mutate(
        values = rnorm(mean = 10, sd = 2, n = n())
      )
    
    ojs_define(plot_data=df)
    ```
    
    ```{ojs}
    import { aq } from '@uwdata/arquero'
    d3 = require("d3@7")
    parser = d3.timeParse("%Y-%m-%d");
    ```
    
    ## Plot
    
    ```{ojs}
    final_data = aq.from(transpose(plot_data))
      .derive({ day: aq.escape(d => parser(d.day)) })
    ```
    
    ```{ojs}
    Chart = Plot.plot({
      marks: [
        Plot.line(final_data, 
          {x: "day", y: "values"}, 
          { stroke: "black" }
        )
      ]}
    )
    ```
    

    observable plot with datetime axis