Published
Edited
May 2, 2020
Importers
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
special_line =
{
const selectCounty = vl.selectSingle('Select State')
.fields('name')
.init({name: 'AK'})
.bind({name: vl.menu(countries)});

return vl.markLine().data(df)
.select(selectCounty)
.transform({filter: selectCounty})
.encode(
vl.x().fieldQ('value').bin(false),
vl.y().fieldQ('death'),
vl.tooltip(vl.y().count())
)
.width(600)
.height(500)
.render()
}
Insert cell
Insert cell
viewof point = html`<input type=file accept="*">`
Insert cell
point_image = d3.csvParse(await Files.text(point))
Insert cell
vegalite({
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {"url": 'https://gist.githubusercontent.com/rigogsoto/e4182f1fa64a1210b6c7a8c6f92eba65/raw/ad54d5b4bc2eb8ef91bcb2a8119eb09883b03d2f/safsdj.csv'},
"layer": [
{
"selection": {"brush": {"type": "interval", "encodings": ["x"]}},
"mark": "bar",
"encoding": {
"x": {"field": "name", "type": "ordinal"},
"y": {
"aggregate": "mean",
"field": "negative",
"type": "quantitative"
},
"opacity": {
"condition": {"selection": "brush", "value": 1},
"value": 0.7
}
}
},
{
"transform": [{"filter": {"selection": "brush"}}],
"mark": "rule",
"encoding": {
"y": {
"aggregate": "mean",
"field": "negative",
"type": "quantitative"
},
"color": {"value": "green"},
"size": {"value": 3}
}
}
]
})
Insert cell
vegalite({
"$schema": "https://vega.github.io/schema/vega-lite/v4.json",
"data": {
"url": "https://gist.githubusercontent.com/KevinK88/2a8f61ee702514363994da0a55930e91/raw/34b65b417875e5bce0fb534799f75593740ac515/deathincrease.csv"
},
"width": 400,
"height": 300,
"layer": [
{
"encoding": {
"x": {"field": "date", "type": "temporal"},
"y": {"field": "deathIncrease", "type": "quantitative"},
"color": {"field": "state", "type": "nominal"}
},
"layer": [
{"mark": "line"},
{
"selection": {
"label": {
"type": "single",
"nearest": true,
"on": "mouseover",
"encodings": ["x"],
"empty": "none"
}
},
"mark": "point",
"encoding": {
"opacity": {
"condition": {"selection": "label", "value": 1},
"value": 0
}
}
}
]
},
{
"transform": [{"filter": {"selection": "label"}}],
"layer": [
{
"mark": {"type": "rule", "color": "gray"},
"encoding": {
"x": {"type": "temporal", "field": "date", "aggregate": "min"}
}
},
{
"encoding": {
"text": {"type": "quantitative", "field": "deathIncrease"},
"x": {"type": "temporal", "field": "date"},
"y": {"type": "quantitative", "field": "deathIncrease"}
},
"layer": [
{
"mark": {
"type": "text",
"stroke": "white",
"strokeWidth": 2,
"align": "left",
"dx": 5,
"dy": -5
}
},
{
"mark": {"type": "text", "align": "left", "dx": 5, "dy": -5},
"encoding": {
"color": {"type": "nominal", "field": "symbol"}
}
}
]
}
]
}
]
}
)
Insert cell
Insert cell
Insert cell
names = new Set(df.map(d => d.name))
Insert cell
datevalues = Array.from(d3.rollup(df, ([d]) => d.value, d => d.date, d => d.name))
.map(([date, data]) => [new Date(date), data])
.sort(([a], [b]) => d3.ascending(a, b))
Insert cell
function legend({
color,
title,
tickSize = 6,
width = 320,
height = 44 + tickSize,
marginTop = 18,
marginRight = 0,
marginBottom = 16 + tickSize,
marginLeft = 0,
ticks = width / 64,
tickFormat,
tickValues
} = {}) {

const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible")
.style("display", "block");

let tickAdjust = g => g.selectAll(".tick line").attr("y1", marginTop + marginBottom - height);
let x;

// Continuous
if (color.interpolate) {
const n = Math.min(color.domain().length, color.range().length);

x = color.copy().rangeRound(d3.quantize(d3.interpolate(marginLeft, width - marginRight), n));

svg.append("image")
.attr("x", marginLeft)
.attr("y", marginTop)
.attr("width", width - marginLeft - marginRight)
.attr("height", height - marginTop - marginBottom)
.attr("preserveAspectRatio", "none")
.attr("xlink:href", ramp(color.copy().domain(d3.quantize(d3.interpolate(0, 1), n))).toDataURL());
}

// Sequential
else if (color.interpolator) {
x = Object.assign(color.copy()
.interpolator(d3.interpolateRound(marginLeft, width - marginRight)),
{range() { return [marginLeft, width - marginRight]; }});

svg.append("image")
.attr("x", marginLeft)
.attr("y", marginTop)
.attr("width", width - marginLeft - marginRight)
.attr("height", height - marginTop - marginBottom)
.attr("preserveAspectRatio", "none")
.attr("xlink:href", ramp(color.interpolator()).toDataURL());

// scaleSequentialQuantile doesn’t implement ticks or tickFormat.
if (!x.ticks) {
if (tickValues === undefined) {
const n = Math.round(ticks + 1);
tickValues = d3.range(n).map(i => d3.quantile(color.domain(), i / (n - 1)));
}
if (typeof tickFormat !== "function") {
tickFormat = d3.format(tickFormat === undefined ? ",f" : tickFormat);
}
}
}

// Threshold
else if (color.invertExtent) {
const thresholds
= color.thresholds ? color.thresholds() // scaleQuantize
: color.quantiles ? color.quantiles() // scaleQuantile
: color.domain(); // scaleThreshold

const thresholdFormat
= tickFormat === undefined ? d => d
: typeof tickFormat === "string" ? d3.format(tickFormat)
: tickFormat;

x = d3.scaleLinear()
.domain([-1, color.range().length - 1])
.rangeRound([marginLeft, width - marginRight]);

svg.append("g")
.selectAll("rect")
.data(color.range())
.join("rect")
.attr("x", (d, i) => x(i - 1))
.attr("y", marginTop)
.attr("width", (d, i) => x(i) - x(i - 1))
.attr("height", height - marginTop - marginBottom)
.attr("fill", d => d);

tickValues = d3.range(thresholds.length);
tickFormat = i => thresholdFormat(thresholds[i], i);
}

// Ordinal
else {
x = d3.scaleBand()
.domain(color.domain())
.rangeRound([marginLeft, width - marginRight]);

svg.append("g")
.selectAll("rect")
.data(color.domain())
.join("rect")
.attr("x", x)
.attr("y", marginTop)
.attr("width", Math.max(0, x.bandwidth() - 1))
.attr("height", height - marginTop - marginBottom)
.attr("fill", color);

tickAdjust = () => {};
}

svg.append("g")
.attr("transform", `translate(0,${height - marginBottom})`)
.call(d3.axisBottom(x)
.ticks(ticks, typeof tickFormat === "string" ? tickFormat : undefined)
.tickFormat(typeof tickFormat === "function" ? tickFormat : undefined)
.tickSize(tickSize)
.tickValues(tickValues))
.call(tickAdjust)
.call(g => g.select(".domain").remove())
.call(g => g.append("text")
.attr("x", marginLeft)
.attr("y", marginTop + marginBottom - height - 6)
.attr("fill", "currentColor")
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(title));

return svg.node();
}
Insert cell
nameframes = d3.groups(keyframes.flatMap(([, data]) => data), d => d.name)
Insert cell
keyframes = {
const keyframes = [];
let ka, a, kb, b;
for ([[ka, a], [kb, b]] of d3.pairs(datevalues)) {
for (let i = 0; i < k; ++i) {
const t = i / k;
keyframes.push([
new Date(ka * (1 - t) + kb * t),
rank(name => (a.get(name) || 0) * (1 - t) + (b.get(name) || 0) * t)
]);
}
}
keyframes.push([new Date(kb), rank(name => b.get(name) || 0)]);
return keyframes;
}
Insert cell
margin = ({top: 16, right: 6, bottom: 6, left: 0})
Insert cell
barSize = 38
Insert cell
height = 782
Insert cell
x = d3.scaleLinear([0, 1], [margin.left, width - margin.right - 50])
Insert cell
function entity(character) {
return `&#${character.charCodeAt(0).toString()};`;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
k = 10
Insert cell
duration = 200
Insert cell
Insert cell
n = 20
Insert cell
viewof keyframe = Scrubber(keyframes, {
format: ([date]) => formatDate(date),
delay: duration,
loop: false
})
Insert cell
viewof replay = html`<button>Replay`
Insert cell


chart = {

replay
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const updateBars = bars(svg);
const updateAxis = axis(svg);
const updateLabels = labels(svg);
const updateTicker = ticker(svg);

yield svg.node();

for (const keyframe of keyframes) {
const transition = svg.transition()
.duration(duration)
.ease(d3.easeLinear);

// Extract the top bar’s value.
x.domain([0, keyframe[1][0].value]);

updateAxis(keyframe, transition);
updateBars(keyframe, transition);
updateLabels(keyframe, transition);
updateTicker(keyframe, transition);

invalidation.then(() => svg.interrupt());
await transition.end();
}
}
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