General

  • Need to render whole document (i.e. not interactive)

  • each cell is separate JavaScript script

  • errors only affect affected cell

  • ? semicolon required after each statement

  • ? risk of deductive disclosure if whole data embedded

  • could add button to read in file

Adding CSS

```{ojs}
html`<style>
h1 {
  color: #006600;
}
</style>`
```

Reading data from R

  • ojs_define function can be used in R or Python
```{r}
library(data.table)
mydatainr <- fread('data.csv')
ojs_define(mydatainojs = mydatainr)
```
```{ojs}
//| echo: true
mydata = transpose(mydatainojs)
// Remember to transpose
mydata
```

Reading data from local file

```{ojs}
mydata2 = FileAttachment("data.csv").csv({typed: true })
mydata2
```
  • alternatively read data directly (no need to transpose it seems)
  • FileAttachment presumably in stdlib so no need to import
  • core libraries are stdlib, Inputs and Plot
  • other JS libraries require importing
  • typed: true for type coercion
  • NB: allow columns with same name

Reading CSV data from Web or local file

```{ojs}
mydata3 = d3.csv('data.csv')
mydata3
```
  • no need to transpose
  • no need to import d3 in Quarto
  • similar method for JSON
  • need to try with DHIS 2 API

View data

```{ojs}
Inputs.table(mydata3)
```
  • no need to import Inputs in Quarto
  • also has useful .range, .checkbox methods

Dealing with duplicate variable names

  • from here - removed the squiggle
```{ojs}
function csvParseDuplicate(text, {empty = "_default", dedup = (name, j) => `${name}${j}`} = {}) {
  const columns = [];
  return Object.assign(d3.csvParseRows(text, (row, i) => {
    if (i === 0) {
      for (let name of row) {
        let n = name || (name = empty);
        let j = 0;
        while (columns.includes(n)) n = dedup(name, ++j);
        columns.push(n);
      }
      return;
    }
    return Object.fromEntries(columns.map((c, i) => [c, row[i]]));
  }), {columns});
}
mydata4 = FileAttachment('data.csv').text()
mydata5 = csvParseDuplicate(mydata4)
mydata5
```
  • see below for how to handle spaces in variable names

Converting to Arquero format

```{ojs}
import {aq, op} from '@uwdata/arquero'
mydata6 = aq.from(mydata5)
mydata6.view()
```

Data transformation

New column values

```{ojs}
mydata7 = mydata6.derive({newdate: d => op.parse_date(d.Period)})
mydata7.view()
```
  • note that you need to reassign

Filtering and aggregation in Arquero

```{ojs}
plot1data = mydata7
  .filter(d => d['Organisation unit1'] == 'Sindh')
  .groupby(['Organisation unit2', 'Data'])
  .rollup({
  mysum: op.sum('Value')
})
plot1data.view()
```

Bar chart

```{ojs}
Plot.plot({
  facet: {
    data: plot1data,
    y: 'Organisation unit2'
},
  marginLeft: 300,
  marginRight: 300,
  grid: true,
  height: 3000,
  marks: [
    Plot.barX(plot1data, {x: "mysum",
    y: "Data",
    fill: "#006600",
    sort: {y: "x", reverse: true}}),
    Plot.ruleY([0])
  ]
})
// FIXME overlapping axis label on right
```

Variables

```{ojs}
myvariable = 'hello world'
```
```{ojs}
myvariable
```

Resources

Good cheatsheet