Public
Edited
Jul 7
Insert cell
Insert cell
Insert cell
topo = FileAttachment("chicagoNeighborhoods.json").json()
Insert cell
crimes = FileAttachment("chicago_crimes_april_2025@1.csv").csv({typed: true}).then(function (data) {
// The date has a special formating not automatically detected by d3,
// so we need to parse it using UTC rather than local time
const parseDate = d3.utcParse("%m/%d/%Y %I:%M:%S %p");
data.forEach(function(d) {
d.Date = parseDate(d.Date);
});
return data;
})
Insert cell
Insert cell
vis = vl.hconcat(
map_view,
vl.vconcat(
vl.markBar()
.title('Number of Crimes by Type')
.data(crimes)
.encode(
vl.x().fieldN("Primary Type"),
vl.y().count(),
vl.color().fieldN("Primary Type")
.scale({
domain: ["HOMICIDE", "BURGLARY", "ROBBERY"],
range: ["#ab0768", "#169d99", "#b9cc01"]
}),
vl.opacity().if(selection, vl.value(1)).value(0.1)
)
.width(width * 0.3)
.height(200)
.select(selection),

vl.markLine()
.title('Number of Crimes by Day')
.data(crimes)
.encode(
vl.x().fieldT("Date").timeUnit("yearmonthdate"),
vl.y().count(),
vl.color().fieldN("Primary Type")
.scale({
domain: ["HOMICIDE", "BURGLARY", "ROBBERY"],
range: ["#ab0768", "#169d99", "#b9cc01"]
}),
vl.opacity().if(selection, vl.value(1)).value(0.1)
)
.width(width*0.3)
.height(200)
)
).render()
Insert cell
map_view = {
const map = vl.markGeoshape({fill: '#ddd', stroke: '#fff', strokeWidth: 1})
.data(vl.topojson(topo).feature('chicago_neighborhoods'))

const circles = vl.markCircle({
size: 30,
opacity: 1,
stroke: '#000',
strokeWidth: 0.3
})
.data(crimes)
.transform(
vl.filter(selection)
)
.encode(
vl.latitude().fieldQ('Latitude'),
vl.longitude().fieldQ('Longitude'),
vl.color().fieldN("Primary Type")
.scale({
domain: ["HOMICIDE", "BURGLARY", "ROBBERY"],
range: ["#ab0768", "#169d99", "#b9cc01"]
}),
vl.tooltip([
{ field: "Primary Type", type: "nominal", title: "Crime Type" },
{ field: "Date", type: "temporal", timeUnit: "yearmonthdatehoursminutes", title: "Date & Time" }
])
)

return vl.layer(map, circles)
.project(
vl.projection('mercator')
)
.width(width*0.3)
.height(400)
}
Insert cell
selection = vl.selectPoint("selection")
.fields("Primary Type")
.on("click");
Insert cell
import {vl} from '@vega/vega-lite-api-v5'
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