Published
Edited
May 7, 2021
2 forks
20 stars
Insert cell
md`# tidy.js - prep data for Multi-Line Charts

Let's look at how we can use tidy.js to help us prep data for [multi-line charts](https://observablehq.com/@d3/multi-line-chart)`
Insert cell
Insert cell
Table(inputData)
Insert cell
Insert cell
Insert cell
tallData = tidy(
inputData,
pivotLonger({ cols: ['-name'], namesTo: 'month', valuesTo: 'value' }),
mutate({ value: d => +d.value })
)
Insert cell
Table(tallData)
Insert cell
Insert cell
groupedTallData = tidy(tallData, groupBy('name', groupBy.entriesObject()))
Insert cell
Table(groupedTallData)
Insert cell
Insert cell
groupedTallData2 = tidy(
tallData,
groupBy(
'name',
groupBy.entries({
mapEntry: ([key, values]) => ({ name: key, values }),
mapLeaf: d => d.value
})
)
)
Insert cell
Table(groupedTallData2)
Insert cell
Insert cell
series = tidy(
inputData,
// make data tall (one object per value)
pivotLonger({ cols: ['-name'], namesTo: 'month', valuesTo: 'value' }),

// make value a number
mutate({ value: d => +d.value }),

// export into our desired shape with `name, values` as field names
groupBy(
'name',
groupBy.entries({
mapEntry: ([key, values]) => ({ name: key, values }),
mapLeaf: d => d.value
})
)
)
Insert cell
Insert cell
simpleMonths = Object.keys(inputData[0]).slice(1)
Insert cell
tidyMonths = tidy(tallData, distinct('month'), map(d => d.month))
Insert cell
Insert cell
simpleDates = tidyMonths.map(d3.utcParse("%Y-%m"))
Insert cell
Insert cell
tidyDates = tidy(
tallData,
distinct('month'),
mutate({ date: d => d3.utcParse('%Y-%m')(d.month) }),
map(d => d.date)
)
Insert cell
Insert cell
chartData = ({ y: 'Unemployment %', series: series, dates: tidyDates })
Insert cell
import { chart } with { chartData as data } from '@d3/multi-line-chart'
Insert cell
chart
Insert cell
Insert cell
statesSeries = tidy(
inputData,
// make data tall (one object per value)
pivotLonger({ cols: ['-name'], namesTo: 'month', valuesTo: 'value' }),

// make value a number, extract state
mutate({
value: d => +d.value,
state: d => /, (..)/.exec(d.name)[1]
}),

// add in an overall average per month, re-using the "state" field to identify it
groupBy('month', total({ value: mean('value') }, { state: 'Overall' })),

// summarize at the state level for each month
groupBy(['state', 'month'], summarize({ value: mean('value') })),

// export into our desired shape with `name, values` as field names
groupBy(
'state',
groupBy.entries({
mapEntry: ([key, values]) => ({ name: key, values }),
mapLeaf: d => d.value
})
)
)
Insert cell
Table(statesSeries)
Insert cell
chartData2 = ({
y: 'Unemployment % by State',
series: statesSeries,
dates: tidyDates
})
Insert cell
import { xAxis, yAxis, line, hover, height } with {
chartData2 as data
} from '@d3/multi-line-chart'
Insert cell
Insert cell
Insert cell
Insert cell
import {
tidy,
pivotLonger,
groupBy,
mutate,
distinct,
map,
summarize,
mean,
total
} from '@pbeshai/tidyjs'
Insert cell
import { Table } from "@observablehq/inputs"
Insert cell
tsvInput = await FileAttachment("unemployment.tsv").text()
Insert cell
inputData = d3.tsvParse(tsvInput)
Insert cell
d3 = require("d3@^6.1")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more