Public
Edited
Feb 10
1 fork
18 stars
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

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more