Public
Edited
Oct 1, 2023
1 star
Insert cell
Insert cell
Insert cell
population_file = {
const fileBuffer = await FileAttachment('12411-01-01-4_flat.csv').arrayBuffer()
// Source file is encoded using ISO 8859-1 / Windows-1252:
const windows1252 = new TextDecoder('windows-1252')
return windows1252.decode(fileBuffer)
}
Insert cell
students_file = {
const fileBuffer = await FileAttachment('21311-01-01-4_flat.csv').arrayBuffer()
// Source file is encoded using ISO 8859-1 / Windows-1252:
const windows1252 = new TextDecoder('windows-1252')
return windows1252.decode(fileBuffer)
}
Insert cell
Insert cell
population_data = aq.fromCSV(population_file, { delimiter: ';', decimal: ','})
Insert cell
// Source file uses semicolons as delimiters and commas as decimal separators
students_data = aq.fromCSV(students_file, { delimiter: ';', decimal: ','})
Insert cell
Insert cell
students = students_data
.select({
'1_Auspraegung_Label': 'region',
'1_Auspraegung_Code': 'ags',
'2_Auspraegung_Label': 'geschlecht',
'3_Auspraegung_Label': 'nation',
'4_Auspraegung_Label': 'fach',
'HS-W02__Studierende_(im_Kreisgebiet)__Anzahl': 'studierende'
})
Insert cell
Insert cell
Insert cell
Insert cell
students_totals = students
.filter(d => d['nation'] === 'Insgesamt')
.filter(d => d['geschlecht'] === 'Insgesamt')
.filter(d => d['fach'] === 'Insgesamt')
.select('region', 'ags', 'studierende')

Insert cell
Insert cell
population_totals = population_data
.filter(d => d['2_Auspraegung_Label'] === 'Insgesamt')
.select({
'1_Auspraegung_Code': 'ags',
'BEVSTD__Bevoelkerungsstand__Anzahl': 'population'
})
Insert cell
Insert cell
Insert cell
students_per_population = students_totals
.join(population_totals, 'ags') // Join by AGS
.derive({ rate: d => d['studierende'] / d['population'] * 10000 || 0 }) // Calculate rate per 10000
Insert cell
Insert cell
Insert cell
choropleth_data = students_per_population
.derive({ ags: d => d.ags == '02' || d.ags == '11' ? `${d.ags}000` : d.ags }) // Fix AGS for Berlin and Hamburg
.filter(d => d['ags'].length === 5) // Filter regions that are not Kreise (5 digits = NUTS 3)
.filter(d => +d['population']) // Filter out historic regions (no population)

Insert cell
Insert cell
{
let values = new Map(choropleth_data.objects().map(({ags, rate}) => [ags, rate]))
return Plot.plot({
projection: {
type: "mercator",
domain: choropleth_regions
},
marks: [
Plot.geo(choropleth_regions, {
fill: (d) => values.get(d.properties['AGS']),
}),
Plot.geo(choropleth_regions, {
stroke: 'grey',
strokeWidth: 0.5
})
],
color: {
scheme: "blues",
type: "linear",
legend: true,
label: "Studierende pro 10.000 Einwohner"
}
})
}
Insert cell
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