Public
Edited
Jan 21
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
import { vl } from "@vega/vega-lite-api"
Insert cell
Insert cell
Insert cell
CH = d3.csvParse(await FileAttachment("CH.csv").text(), d3.autoType)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
// Always start a vega-lite chart with "vl"
vl
// We can then chain vega-lite functions with a dot ".",
// starting with the mark:
.markCircle() // try .markBar() or .markPoint()
// use the dataset that we defined above:
.data(CH)
// invoking .render() draws the plot:
.render()
Insert cell
Insert cell
Insert cell
vl.markCircle()
.data(CH)
.encode(
// 1. Encode `elected` on the y axis
vl.y().field("elected").type("quantitative"),
// 2. Encode `year` on the x axis
vl.x().field("year").type("ordinal"), // type "ordinal" can be used here as years are ordered strings.
// 3. Use color to encode the dimension `gender`:
vl.color().fieldN("gender"), // shortcut for field & type definition: fieldN("gender")
)
.render()
Insert cell
Insert cell
Insert cell
Insert cell
vl.markArea() // Try using .markArea(), .markLine() or .markBar()
.data(CH)
.encode(
vl.x().fieldO("year"),
vl.y().fieldQ("elected"),
vl.color().fieldN("gender"),
// Try using additional encoding channel:
// vl.tooltip(["year", "elected", "gender"]),
// vl.facet().fieldN("gender"),
//vl.opacity().value(.6)
)
.render()
Insert cell
Insert cell
vl.markLine({
interpolate: "monotone" // "step" | "linear" | "monotone" | ...
})
.title("No gender parity in the Swiss National Council")
.width(400)
.height(200)
.data(CH)
.encode(
vl.x().fieldO("year")
.title('Year of election'),
vl.y().fieldQ("elected")
.title('Number of MP in the National Council')
.axis({ tickCount: 2 }),
vl.color().fieldN("gender")
.scale({ domain: ["Frau", "Mann"], range: ["orange", "gray"] })
.title(null)
.legend({ orient: "top" }),
vl.strokeWidth().value(3),
// vl.strokeDash().fieldN("gender")
)
.render(
{renderer: "SVG" }
)
Insert cell
Insert cell
Insert cell
Insert cell
vl.markArea()
.data(CH)

// Let's focus on the number for women in the Council:
.transform(
vl.filter("datum.gender === 'Frau' ")
)

.encode(
vl.x().fieldO("year"),
vl.y().fieldQ("elected"),
vl.color().fieldN("gender")
.scale({ domain: ["Frau", "Mann"], range: ["orange", "gray"] })
)
.render()
Insert cell
Insert cell
Insert cell
vl.markBar()
.data(CH)
.transform(
vl.groupby("gender").aggregate(
vl.average("elected").as("gender_aggregated")) // Try median or sum
)
.encode(
vl.x().fieldN("gender"),
vl.y().fieldQ("gender_aggregated"),
vl.tooltip(["gender_aggregated"]),
vl.color().fieldN("gender")
.scale({ domain: ["Frau", "Mann"], range: ["orange", "gray"] })
)
.render()
Insert cell
Insert cell
Insert cell
vl.markPoint({ size: 70, color: "black" })
.data(CH)
.transform(
vl.groupby("year")
.pivot("gender")
.value("elected")
)
.encode(
// Two new field names added by the transformation
vl.x().fieldQ("Frau")
.axis({ titleColor: "orange", titleFontSize: 16 }),
vl.y().fieldQ("Mann")
.axis({ titleColor: "gray", titleFontSize: 16 }),
)
.render()
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
vl.markArea()
.encode(
vl.x().fieldN("year"),
vl.y().fieldQ("elected"),
vl.color().fieldN("gender")
.scale({ domain: ["Frau", "Mann"], range: ["orange", "gray"] }),
vl.tooltip(["year", "gender", "elected"])
)
.width(500)
.height(100)

// We can create small multiples using "facets":
.facet({ row: vl.field("party") })

.data(parties)
.render()
Insert cell
Insert cell
{
const points = vl.markCircle()
.encode(
vl.x().fieldQ("proportion_of_women")
.sort(vl.field("year").order("ascending")),
vl.y().fieldQ("number_of_seats")
.sort(vl.field("year").order("ascending")),
vl.color().fieldN("party")
.scale({ domain: ["CVP", "FDP", "SP", "SVP"], range: ['#D6862B', '#3872B5','#F0554D','#4B8A3E']}),
// Note the use of a conditional circle size to highlight 2019:
vl.size().if("datum.year === 2019", vl.value(100)).value(30),
vl.fillOpacity().value(2),
vl.tooltip(["year", "party", "proportion_of_women"])
)
.width(150)
.height(150)
const lines = points.markLine({ interpolate: "monotone" })
.encode(
vl.size().value(1)
)

// We can layer points on top of lines using vl.layer():
return vl.layer(points, lines)
.facet(vl.field("party"))
.data(parties)
.transform(
vl.groupby(["year", "party"]).pivot("gender").value("elected"),
vl.calculate("datum.Frau + datum.Mann").as("number_of_seats"),
vl.calculate("(datum.Frau / datum.number_of_seats) * 100").as("proportion_of_women")
)
.render({renderer: "SVG"});
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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