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
Adding CSS
```{ojs}
html`<style>
h1 {
color: #006600;
}
</style>`
```Reading data from R
ojs_definefunction can be used in R or Python
```{r}
library(data.table)
mydatainr <- fread('data.csv')
ojs_define(mydatainojs = mydatainr)
```- NB: need to transpose
- chunk options prefixed by
//| - hard to override
<-muscle memory!
```{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)
FileAttachmentpresumably instdlibso no need to import- core libraries are
stdlib, Inputs and Plot - other JS libraries require importing
typed: truefor 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,.checkboxmethods
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
-
“invalid module”
-
but does work in browser
-
Plot.barYfor vertical columns -
Plot.barXfor horizontal columns -
marginLeftto increase space for labels
```{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
```